温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

react-router 学习笔记

发布时间:2020-08-03 21:08:30 来源:网络 阅读:550 作者:张涛泽 栏目:网络安全

前言:

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

一、路由基础

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

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

react-router 学习笔记

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

react-router 学习笔记

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

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

react-router 学习笔记

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

react-router 学习笔记

 

二、默认路由(IndexRoute )

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

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

react-router 学习笔记

render((    <Router history={ hashHistory }>         <Route path="/" component={ App }>             <IndexRoute component={ IndexApp } />             <Route path="select" component={ Select }></Route>             <Route path="found" component={ Found }></Route>             <Route path="follow" component={ Follow }></Route>             <Route path="my" component={ My }>                 <Route path=":myname" component={ MyName }></Route>                 <Route path="mysex" component={ MySex }></Route>             </Route>         </Route>     </Router>), document.getElementById('root'));

react-router 学习笔记

 

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

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

三、路由跳转   

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

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

<Link to="/my" >Mypage</Link> <Link to="/my/:myname" >myname</Link>

 

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

<IndexLink to="/my" >Mypage</IndexLink> <Link to="/my/:myname" >myname</Link>

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

  2.跳转参数 to

     2.1:通过 to=’xx/xx' 直接跳转 <Link to={`/my/${myname}/info`}>check my info</Link> 

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

 <li><Link to={{pathname:"/select", hash:'#ahash', query:{foo: 'bar', boo:'boz'}, state:{data:'miao'}  }} activeClassName="GlobalNav-active">精选</Link></li>

     2.3:to=函数,注册到路由跳转事件中,每一次路由变化,都会执行该函数,并经最新的location作为参数

<Link to={location => ({ ...location, query: { name: 'ryan' } })}>   Hello</Link>

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

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

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

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

react-router 学习笔记

    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'}         })     }

react-router 学习笔记

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

    若不使用Link,有两种方法

    3.1 contextTypes

react-router 学习笔记

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

react-router 学习笔记

 

    3.2 引入browserHistory,hashHistory

react-router 学习笔记

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

react-router 学习笔记

 

四、重定向

  <Redirect>:重定向到同等级的其他路由

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

react-router 学习笔记

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

react-router 学习笔记

 

  <IndexRedirect>:从父路由的目录开始重定向

<Route path="/" component={App}>   <IndexRedirect to="/welcome" />   <Route path="welcome" component={Welcome} />   <Route path="about" component={About} /> </Route>

 

 

五、路由机制的权限

  1.onEnter

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

  nextState的属性

react-router 学习笔记

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

react-router 学习笔记

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

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

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

   

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

<Route path="follow" component={ Follow }></Route> // this.props.children;<Route path="follow" component={ {main:Follow, sidebar: Sidebar} }></Route> // 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 学习笔记

 

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

react-router 学习笔记

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(    <Router history={browserHistory} routes={rootRouter} />,     document.getElementById('root') )

react-router 学习笔记

 

   代码分割的注意事项:

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

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

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


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI