路由
基本使用
import React, { lazy, Suspense } from 'react';
// 引入全局css
import './assets/css/index.css';
import { BrowserRouter, Switch, Redirect} from 'react-router-dom';
import PrivateRoute from './utils/privateRoute.js'; //私有路由
// 加载路由页面组件
const Home = lazy(() => import('./pages/home'));
const Login = lazy(() => import('./pages/login'));
const NotFound = lazy(() => import('./pages/notFound'));
{/*
路由使用备注
1.路由的放置顺序非常重要(如果我们在每个路由上都添加 exact 那么它们的顺序可以随意调整,这是另一种选择)
2.路由组件只在和地址中的路由匹配时才渲染
3.使用 switch 就会只匹配一组路由中的一个
4.注: 访问 "/index/welcome" 时 "/", "/index", "/index/welcome"都会被匹配
所有前两个要加 exact 做排他性处理
若将 "/", "/index" 放置到最下边 则不用加 exact
5.在<Switch> 中,其它的路由没有匹配时,才会渲染重定向组件Redirect
6.一个路由地址, 可在多个switch中显示多个路由组件
7.路由守卫功能需要 使用自定义高阶路由组件实现
8. 配合Suspense和lazy实现路由页面的懒加载 Suspense的fallback中可以提供一个loading组件
9. PrivateRoute私有路由是和vue类似的路由守卫
*/}
{
/* react-router v4 无排他性 一个路由可匹配多个组件
exact起排他性作用 若不加这个,
当访问/login时 index 和login都会被渲染
*/
}
function App() {
return (
<BrowserRouter>
<Suspense fallback={null}>
<Switch>
// isAuth : 是否登录后才能访问(私有路由实现参数)
<PrivateRoute path="/" component={Home} exact></PrivateRoute>
<PrivateRoute path="/home" component={Home}></PrivateRoute>
<PrivateRoute path="/login" component={Login}></PrivateRoute>
{/* 针对路由地址含有其他内容 可在命名上或放置顺序上动手脚 或者 加上exact*/}
{/* 第一种方式 加 exact*/}
{/* <PrivateRoute isAuth={true} path="/articles" exact component={Articles}></PrivateRoute> */}
{/* params定义传参 */}
{/* <PrivateRoute isAuth={true} path="/articles/detail/:id" component={ArticlesDetail}></PrivateRoute> */}
{/* search定义传参 */}
{/* <PrivateRoute isAuth={true} path="/articles/detail" component={ArticlesDetail}></PrivateRoute> */}
{/* 第二种方式 调换放置顺序*/}
{/*
<Route path="/articles/detail" component={ArticlesDetail}></Route>
<Route path="/articles" component={Articles}></Route>
*/}
{/* 第三种方式 命名动手脚*/}
{/*
<Route path="/articlesDetail" component={ArticlesDetail}></Route>
<Route path="/articles" component={Articles}></Route>
*/}
<PrivateRoute path="/notFound" component={NotFound}></PrivateRoute>
<Redirect to="/notFound"/>
</Switch>
</Suspense>
</BrowserRouter>
);
}
export default App;
私有路由(路由守卫)
import React, { Component } from 'react';
import { Route, withRouter, Redirect} from 'react-router-dom';
// import PropTypes from 'prop-types';
//私有路由,只有登录的用户才能访问
class PrivateRoute extends Component {
constructor(props){
super(props);
this.state = {
// 是否有存储登录后的信息
isAuthenticated: true
}
}
doSomesing() {
console.log('doSomesing');
}
render(){
// render中不能使用this.setState的函数 否则会造成死循环
// 此处必须返回些什么
// 返回的内容得是路由跳转相关的 route 或 Redirect 要不继续正常跳转 要不就强制跳转其他页面
// 返回之前做些操作
// this.doSomesing();
console.log('路由钩子 beforeEnterRoute', this.props.match);
let isAuthenticated = localStorage.getItem("doctorUserInfo") ? true :false;
let { component: Component, path, exact=false, strict=false } = this.props;
{
if(this.props.isAuth && !isAuthenticated){
return <Redirect to="/login"/>
}else{
// return <Route path={path} exact={exact} strict={strict} component={Component} />
return <Route path={path} exact={exact} strict={strict} render={(props)=>( <Component {...props} /> )} />
}
}
}
// //如果没有传递该属性时的默认值
static defaultProps = {
// 当前路由是否需要验证登录
isAuth: false
}
// //如果传递该属性,该属性值必须为字符串
// static propTypes={
// path:PropTypes.string.isRequired,
// exact:PropTypes.bool,
// strict:PropTypes.bool,
// component:PropTypes.func.isRequired,
// isAuth:PropTypes.bool, //是否需要登录后才能访问
// }
}
export default withRouter(PrivateRoute);
嵌套路由(子路由)
const Content = lazy(() => import('../content'));
const ArticlesDetail= lazy(() => import('../articlesDetail'));
render() {
return (
<div className="layout">
<div className="main-box">
<Switch>
// 当前为 /hoem 路由的子路由
// 所有子路由需要以 /home/ xxx 开头
// isAuth : 是否登录后才能访问(私有路由实现参数)
<PrivateRoute path="/home/content" component={Content}></PrivateRoute>
<PrivateRoute isAuth={true} path="/home/articles/detail" component={ArticlesDetail}></PrivateRoute>
<Redirect to="/home/content"></Redirect>
</Switch>
</div>
</div>
</div>
);
}
路由传参
react定义了多种方式
但需要满足以下几点使用要求
1 书写方便; 2刷新参数不消失;3参数可在地址栏显示(链接在其他地方也可访问)
所以选用search的传参方式
// 路由注册:
<PrivateRoute isAuth={true} path="/home/articles/detail" component={ArticlesDetail}></PrivateRoute>
// 触发跳转
this.props.history.push( `/home/articles/detail/?id=${id}`)
//参数接收
// 此种传参方式 参数写在地址字符串中 需要解析出来
import { querySearch } from '../../utils/utils';
let search = querySearch(this.props.location.search);
querySearch的实现
安转插件
npm i querystring -S
// utils/ulils.js文件
import qs from 'querystring';
// 解析search传参
export const querySearch = (string) => {
return qs.parse(string.slice(1))
}
另注:可以考虑使用react-router-config, 这是一个辅助react-router的插件,主要是使用配置文件集中式管理路由。