加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

react-router 学习笔记

发布时间:2020-12-15 07:23:59 所属栏目:百科 来源:网络整理
导读:前言: 本文为个人学习react-router的总结。包括路由基础配置,跳转,权限管理,组件与路由配置的关系,代码分割。欢迎交流指导。 一、路由基础 1. 路由配置 显示路由组件的 view (类比angular的ui-view) 路由配置:路由匹配的规则 650) this.width=650;"

前言:

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

一、路由基础

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

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

复制代码

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

复制代码

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

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

复制代码

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

复制代码

二、默认路由(IndexRoute )

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

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

复制代码

render((<Routerhistory={hashHistory}>
<Routepath="/"component={App}>
<IndexRoutecomponent={IndexApp}/>
<Routepath="select"component={Select}></Route>
<Routepath="found"component={Found}></Route>
<Routepath="follow"component={Follow}></Route>
<Routepath="my"component={My}>
<Routepath=":myname"component={MyName}></Route>
<Routepath="mysex"component={MySex}></Route>
</Route>
</Route>
</Router>),255);">  如果不使用IndexRoute组件,也还有一种投机取巧的方法,直接在 App组件中,使用{this.props.children || <IndexApp />},在ui展示的层面上修改this.props.children为undefined的情况。

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

三、路由跳转  

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

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

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

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

<IndexLinkto="/my">Mypage</IndexLink>
<Linkto="/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><Linkto={{pathname:"/select",hash:'#ahash',query:{foo:'bar',boo:'boz'},state:{data:'miao'}}}activeClassName="GlobalNav-active">精选</Link></li>

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

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

    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

复制代码

staticcontextTypes={
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')//...

复制代码

四、重定向

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

  <Redirectfrom=name/xxx"to='mysex'/>

复制代码

render((<Routerhistory={browserHistory}>
<Routepath="/"component={App}>
<IndexRoutecomponent={IndexApp}/>
<Routepath="select"component={Select}></Route>
<Routepath="found"component={Found}onEnter={onEnterHook}onLeave={onLeaveHook}></Route>
<Routepath="follow"component={Follow}>
</Route>
<Routepath="my"component={My}>
<Redirectfrom="name/xxx"to='mysex'/>

<Routepath="name/:myname"component={MyName}>
<Routepath="info"component={MyInfo}></Route>
</Route>
<Routepath="mysex"component={MySex}/>
</Route><Redirectfrom="*"to='/'/>
</Route>
</Router>),255);">  <IndexRedirect>:从父路由的目录开始重定向

<Routepath="/"component={App}>
<IndexRedirectto="/welcome"/>
<Routepath="welcome"component={Welcome}/>
<Routepath="about"component={About}/>
</Route>

五、路由机制的权限

  1.onEnter

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

  nextState的属性

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

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

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

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

  

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

<Routepath="follow"component={Follow}></Route>//this.props.children;<Routepath="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组件的属性

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

复制代码

constselectRouter={
path:'select',component:Select
}constfoundRouter={
path:'found',component:Found
}constmyRouter={
path:'my',getComponent(nextState,cb){
cb(null,My)
}
}//importFollowfrom'./components/Follow.js';constfollowRouter={
path:'follow',require('./components/Follow'))
})
}//getComponent(nextState,cb){//cb(null,Follow)//}}constrootRouter={
path:'/',component:App,//indexRoute:{component:IndexApp},childRoutes:[
selectRouter,foundRouter,followRouter,//require('./components/Follow.index'),myRouter
]
}//constrootRouter={//path:'/',//component:App,//getIndexRoute(partialNextState,{compoment:IndexApp});//},//getChildRoutes(location,[//selectRouter,//foundRouter,//followRouter,//myRouter//])//}//}render(<Routerhistory={browserHistory}routes={rootRouter}/>,document.getElementById('root')
)

复制代码

  代码分割的注意事项:

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

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读