v3和v4有一些差距:
https://blog.csdn.net/qq_35484341/article/details/80500237
以下的总结,都是基于V4的
官方文档:https://reacttraining.com/react-router/web/guides/quick-start
<BrowserRouter/> <HashRouter/> <Route/> <Switch/> <Redirect/> <Link/> (<NavLink/>) withRouter
不多解释,先上实例:
<BrowserRouter> <Link to="/">主页</Link> <Link to="/recommend">推荐</Link> <Link to="/detail/1">详情</Link> <Route path="/" exact component={Home}/> <Route path="/detail/:id" exact component={Detail}/> <Route path="/recommend" exact component={Recomm}/> </BrowserRouter>
这两者可以理解为路由的作用域,所有的Link组件和Route组件都必须在其内部。
浏览器路由和哈希路由的区别:
在BrowserRouter模式下,如何在服务端配置呢?
被渲染成a标签,跟href属性的所用类似。点击Link标签和a标签,看到的效果是一样的,但我们推荐<Link>,使用它才是单页面应用,浏览器不会请求页面;而使用a标签,会重新请求页面。
<Link to=‘/path‘ /> <Link to={ pathname, // 路径,即 to 的字符串用法 search, // search hash, // hash state, // state 对象 action, // location 类型,在点击 Link 时为 PUSH,浏览器前进后退时为 POP,调用 replaceState 方法时为 REPLACE key, // 用于操作 sessionStorage 存取 state 对象 } /> <Link to=‘/path‘ replace={true} /> // 覆盖当前路径
Link的加强版
具体的路由规则
属性:
// 渲染目标 component // 渲染组件 render children // 地址匹配 path <Route path="/hello/:name"> name为参数名,可以在其渲染组件中获取 this.props.params.name <Route path="/files/*.*"> 匹配 /files/hello.jpg 、 /files/hello.html <Route path="/files/*"> 匹配 /files/ 、 /files/a 、 /files/a/b exact // 完全匹配的意思,排他
有<Switch>嵌套,则其中的<Route>在路径相同的情况下,只匹配第一个,这个可以避免重复匹配。
无<Switch>嵌套,则其中的<Route>在路径相同的情况下全都会匹配,包括上级路径。
重定向到新地址
<Redirect to=‘/path‘ />
当用户准备离开该页面时,弹出提示
message: 字符串/函数,离开页面时的提示信息 when:布尔值,通过设定条件决定是否启用该组件
例如:
<Prompt message="您确定要离开该页面吗?" when={this.state.isOpen} /> <Prompt message = {() => {this.state.isOpen? false: "您确定要离开该页面吗?"}} />
被Route绑定的渲染组件,总是被传入三个属性(对象):history、location、match。在渲染组件中也会有很多其他组件,这些组件内部如果想要获取三个对象,需要withRouter(通过装饰器或函数调用的形式都可)。
我们可以用这三个对象完成很多事情。
history实现对会话历史的管理。
length: number 浏览历史堆栈中的条目数 action: string 路由跳转到当前页面执行的动作,分为 PUSH, REPLACE, POP location: object 当前访问地址信息组成的对象,具有如下属性: pathname: string URL路径 search: string URL中的查询字符串 hash: string URL的 hash 片段 state: string 例如执行 push(path, state) 操作时,location 的 state 将被提供到堆栈信息里,state 只有在 browser 和 memory history 有效。 push(path, [state]) 在历史堆栈信息里加入一个新条目。 replace(path, [state]) 在历史堆栈信息里替换掉当前的条目 go(n) 将 history 堆栈中的指针向前移动 n。 goBack() 等同于 go(-1) goForward 等同于 go(1) block(prompt) 阻止跳转
loaction指当前的位置
{ hash: ‘#sdfas‘, key: ‘sdfad1‘ pathname: ‘/about‘, search: ‘?name=minooo‘ state: { price: 123 } }
可以在不同场景中使用:
<Link to={location} /> <NaviveLink to={location} /> <Redirect to={location /> history.push(location) history.replace(location)
match对象包含了<Route>如何与URL匹配的信息。
params: object 路径参数,通过解析 URL 中的动态部分获得键值对 isExact: bool 为 true 时,整个 URL 都需要匹配 path: string 用来匹配的路径模式,用于创建嵌套的 <Route> url: string URL 匹配的部分,用于嵌套的 <Link>
大致有三种方法:
//路由设置 <Route path=‘ /user/:id ‘ component={User} /> // 传值 <Link to=‘/user/2‘ /> this.props.history.push("/user/2"); // 获取值 this.props.match.params.id
//路由设置 <Route path=‘ /user ‘ component={User} /> // 传值 <Link to=‘/user?id=2‘ /> this.props.history.push("/user?id=2"); // 获取值 this.props.location.seacrh // 获得"?id=2",将其进行拆解即可获得
又有两种方式:
(1)loaction.state。传的参数是加密的
// 路由设置 <Route path=‘ /user ‘ component={User}></Route> // 传值 <Link to={{ pathname:‘ /user‘,state:{id:123},search:‘?sort=name‘,hash:‘#the-hash‘}}> this.props.history.push({pathname:‘ /user‘,state:{id:123},search:‘?sort=name‘,hash:‘#the-hash‘}); // 获取值 this.props.location.state.id
(2)自定义属性
// 路由设置 <Route path=‘ /user ‘ component={User}></Route> // 传值 <Link to={{ pathname:‘ /user‘,abc:{id:123},search:‘?sort=name‘,hash:‘#the-hash‘}}> this.props.history.push({pathname:‘ /user‘,abc:{id:123},search:‘?sort=name‘,hash:‘#the-hash‘}); // 获取值 this.props.location.abc.id
在react-router中,并没有提供导航守卫相关的API,作者这样描述:你可以在渲染功能中实现此功能,JSX不需要API,因为它更灵活。
首先,导航守卫在业务层面可以有三种表现:
在这几种表现中,2和3并不相互冲突。现在有两种思路实现导航守卫:
示例1(业务场景1):
// 路由配置 const routerConfig = [ { path:‘/‘, component:HomePage, auth:false, },{ path:‘/home‘, component:HomePage, auth:true, // 表示必须登录才能访问 },{ path:‘/login‘, component:LoginPage, },{ path:‘/404‘, component:ErrorPage } ]; class RouterTab extends React.Component{ render(){ return( <HashRouter> <Switch> <RouteGenerator config={routerConfig} /> </Switch> </HashRouter> ); } } class RouterGenerator extends React.Coponent{ // 在这里定义限制路由的逻辑(业务场景1) render(){ const routeConf = this.props.config; routeConf.map((conf)=>{ if(conf.auth) // 判断该路由是否满足渲染条件 { if(login) // 判断当前有没有登录 { retrun <Route path={conf.path} component={conf.component} exact={conf.exact?true:false} /> } }else { retrun <Route path={conf.path} component={conf.component} exact={conf.exact?true:false} /> } }); } }
示例2(业务场景3):
// 将此高阶组件修饰所有需要被守卫的路由组件 const routerGuard = (RouteConfig) => { retrun (WrappedComponent) => { rentrun class NewComponent extends React.Component { componentWillMount(){ const path = this.props.location.pathname; const config = RouteConfig.find(f => f.path === path); if(!config) { this.props.history.push("/404"); } if(config.auth && !login) { this.props.history.push("/login"); } } render(){ retrun( <WrappedComponent {...this.props} /> ) } } } }
如果项目特别大,打包后的js文件会特别大。在首次加载时,一次性地将整个js文件发送给浏览器,一次性地加载所有代码,会对浏览器产生比较大的压力,影响用户体验。我们希望的是,只加载当前访问页面相关的js代码,当路由跳转的时候,再请求相应页面的js代码。这需要使用第三方库,做的比较优秀的有 react-loadable 和 react-async-component。
react-loadable的原理是将代码进行分割,分割成若干个chunk.js,需要用到的时候就请求过来。
react-async-component为按需异步加载,使用Promise和高阶组件实现,提高性能。
原文:https://www.cnblogs.com/V587Chinese/p/11507836.html