react-router 学习笔记

前言:

  本文为个人学习react-router的总结。包括路由基础配置,跳转,权限管理,组件与路由配置的关系,代码分割。欢迎交流指导。

一、路由基础

  1.路由配置 & 显示路由组件的view(类比angular的ui-view)

  路由配置:路由匹配的规则

render((
    
        "/" component={ App }>
            "select" component={ Select }>
            "found" component={ Found }>
            "follow" component={ Follow }>
            "my" component={ My }>
                ":myname" component={ MyName }>
                "mysex" component={ MySex }>
            
        
    
), document.getElementById('root'));

  view:放置路由组件的地方(URL匹配了,然后对应的组件应该放到什么地方去),

  每一个Route都只是一个组件,子路由就是 this.props.children 里面的组件,Route通过匹配URL决定显示哪一个子路由

class App extends PureComponent {
    render() {
        return (
            
{ this.props.children } { /* this.props.children 是被嵌套在App的组件,相当于放子路由的View*/}
) } }

 

二、默认路由(IndexRoute )

  组件 的匹配路径是 ‘/', 有四个子路由,当前路由只是'/',那么应该显示什么页面呢?

  这里给与IndexRoute组件 -- 若希望直接使用4个其中一个则使用IndexRedirect

render((
    
        "/" component={ App }>
            
            "select" component={ Select }>
            "found" component={ Found }>
            "follow" component={ Follow }>
            "my" component={ My }>
                ":myname" component={ MyName }>
                "mysex" component={ MySex }>
            
        
    
), document.getElementById('root'));

 

   如果不使用IndexRoute组件,也还有一种投机取巧的方法,直接在 App组件中,使用  {this.props.children || } ,在ui展示的层面上修改this.props.children为undefined的情况。

   缺点:这种形式,没有参与到路由机制中,onEnter,onLeave 等HOOK都无法使用

三、路由跳转   

  1. IndexLink & Link (active状态之争)

   倘若有如下两个链接,正好URL是'/my/mioawwwww', 两个路由都匹配的了,那么就是两个都是active状态(相应地添加activeStyle,activeClassName的样式)

"/my" >Mypage
"/my/:myname" >myname

 

  若你只想为 "/my/:myname" >myname 这一个按钮添加active样式,就可以为 "/my" >Mypage 使用IndexLink

"/my" >Mypage
"/my/:myname" >myname

  IndexLink是补充Link的,只要URL完整匹配'/my'的时候才会激活active状态

  2.跳转参数 to

     2.1:通过 to=’xx/xx' 直接跳转 check my info 

     2.2:to=对象,带参数跳转(pathname, query, hash, state(额外数据)),注意:这些参数都被存放到this.props.location中

 
  • "/select", hash:'#ahash', query:{foo: 'bar', boo:'boz'}, state:{data:'miao'} }} activeClassName="GlobalNav-active">精选
  •      2.3:to=函数,注册到路由跳转事件中,每一次路由变化,都会执行该函数,并经最新的location作为参数

     ({ ...location, query: { name: 'ryan' } })}>
      Hello
    

        2.4:不使用Link,在函数内直接操作router

          旧版本:由于router只用的context传递路由信息,因此每一个组件都可以轻易的通过this.context.router获取路由

          新版本:router被放置在this.props中,通过this.props.router可以获取路由

          注意:push与replace的区别,一个是添加,一个是替换,历史记录中被替换的已经不存在了,所以浏览器回退不到替换前的页面。

        changeRouter = () => {
            console.log(this.props)
            // this.props.router.push('/follow');
            // this.props.router.push({
            //     pathname:'/follow',
            //     state:{name:'xxx'},
            //     query: {foo: 'bar'}
            // })
            
            // this.props.router.replace('/follow');
            this.props.router.replace({
                pathname: '/follow',
                query: {foo:'bar'}
            })
        }

       3.若不是Route组件,而是Route的子组件,则this.props.router === undefined

        若不使用Link,有两种方法

        3.1 contextTypes

        static contextTypes = {
            router: PropTypes.object
        }
        handleClick = (e) => {
            e.stopPropagation();
            e.preventDefault();
            this.context.router.push('login');
                    //...

     

        3.2 引入browserHistory,hashHistory

    import {browserHistory} from 'react-router';
    //...
        handleClick = (e) => {
            e.stopPropagation();
            e.preventDefault();
            browserHistory.push('login')
            //...

     

    四、重定向

      重定向到同等级的其他路由

       from="name/xxx" to='mysex' /> 

    render((
        
            "/" component={ App }>
                
                "select" component={ Select }>
                "found" component={ Found } onEnter={onEnterHook} onLeave={onLeaveHook}>
                "follow" component={ Follow }>
                
                "my" component={ My } >
                    from="name/xxx" to='mysex' />
                    
                    "name/:myname" component={ MyName }>
                        "info" component={ MyInfo } >
                    
                    "mysex" component={ MySex } />
                
                
            
        
    ), document.getElementById('root'));

     

      从父路由的目录开始重定向

    "/" component={App}>
      "/welcome" />
      "welcome" component={Welcome} />
      "about" component={About} />
    

     

     

    五、路由机制的权限

      1.onEnter

    const onEnterHook = (nextState, replace /*,cb*//*若添加cb参数,钩子变成异步执行,cb返回之前,将发生阻塞*/) => {
        console.log('onenter', nextState);
        // replace // 是router.replace(),若访问者没有权限,则引导到其他页面
    }

      nextState的属性

    react-router 学习笔记_第1张图片

      2.onLeave:与onEnter类似,nextState属性不同

    react-router 学习笔记_第2张图片

       3.onChange(prevState, nextState, replace, callback?) ,用于子路由,

        进入该路由的某个子路由是触发,或者改变query,hash

        一旦添加onChange属性,则子路由通过onChangeHook决定,Link不起作用

       

     六、组件与路由的一一对应关系,按需加载组件

    "follow" component={ Follow }> // this.props.children;
    "follow" component={ {main:Follow, sidebar: Sidebar} }> // const { main, sidebar } = this.props;

     

       异步加载组件,使用(需要加上 require.ensure([], (require) => {}) 实现代码分割

       getComponent(nextState, callback)  &&  getComponents(nextState, callback) 

       cb(err, component) 

      getComponent(nextState, cb) {
        require.ensure([], (require) => {
          cb(null, require('./components/Calendar'))
        })
      }

     

       

     七、每一个Route组件的属性

     react-router 学习笔记_第3张图片

     

     八、另一种路由配置的方式

    const selectRouter = {
        path:'select',
        component: Select
    }
    const foundRouter = {
        path:'found',
        component: Found
    }
    const myRouter = {
        path:'my',
        getComponent(nextState,cb) {
            cb(null, My)
        }
    }
    // import Follow from './components/Follow.js';
    const followRouter = {
        path:'follow',
        getComponent(nextState,cb) {
            require.ensure([], (require) => {
                cb(null, require('./components/Follow'))
            })
        }
        // getComponent(nextState, cb) {
        //     cb(null, Follow)
        // }
    }
    const rootRouter = {
        path: '/',
        component: App,
        // indexRoute: {component:IndexApp},
        childRoutes: [
            selectRouter,
            foundRouter,
            followRouter,
            // require('./components/Follow.index'),
            myRouter
            ]
    }
    // const rootRouter = {
    //     path: '/',
    //     component: App,
    //     getIndexRoute(partialNextState, cb) {
    //         cb(null,  {compoment:IndexApp});
    //     },
    //     getChildRoutes(location, cb) {
    //         cb(null, [
    //             selectRouter,
    //             foundRouter,
    //             followRouter,
    //             myRouter
    //         ])
    //     }
    // }
    render(
        ,
        document.getElementById('root')
    )

     

       代码分割的注意事项:

        1. require.ensure中分割的组件,需要使用module.export 暴露出来

    module.exports = xxx; //可获取xxx组件
    export default xxx // 不可获取xxx组件 

         2. getComponent,getComponents,getIndexRoute,getChildRoutes只是实现了异步加载,要实现代码分割还是要使用require.ensure

     

    转载于:https://www.cnblogs.com/miaowwwww/p/6343207.html

    你可能感兴趣的:(react-router 学习笔记)