路由拦截与监听对于一个项目来讲基本是必须要有的,因为只要涉及到登录权限等问题就需要这些功能了,需要将未登录的时候都拦截在登录界面,没有权限的都丢到无权限页面去。
对于VUE来讲, vue-router提供了路由守卫的API方法来让我们非常方便的进行路由监听与拦截处理了,但是我找了好久也没有找到ReactJS相关的API方法,大部分都是一句话:ReactJS的所有东西都是组件,所以只要通过组件的方法来进行实现了。我只是通过度娘搜索总结出的一套方法,不知道有没有更简便方法,如果有请留言,谢谢。
通过组件的方法想要对路由进行监听与拦截,首先想到的是组件的生命周期,因为想要拦截只有在组件生命周期渲染前进行拦截,所以查询ReactJS组件的生命周期有以下方法:参考文章:React的生命周期
1. 挂载卸载过程 1.1.constructor() constructor()中完成了React数据的初始化,它接受两个参数:props和context,当想在函数内部使用这两个参数时,需使用super()传入这两个参数。 注意:只要使用了constructor()就必须写super(),否则会导致this指向错误。 1.2.componentWillMount() componentWillMount()一般用的比较少,它更多的是在服务端渲染时使用。它代表的过程是组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。 1.3.componentDidMount() 组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染 1.4.componentWillUnmount () 在此处完成组件的卸载和数据的销毁。 2. 更新过程 2.1. componentWillReceiveProps (nextProps) 在接受父组件改变后的props需要重新渲染组件时用到的比较多 接受一个参数nextProps 通过对比nextProps和this.props,将nextProps的state为当前组件的state,从而重新渲染组件 componentWillReceiveProps (nextProps) { nextProps.openNotice !== this.props.openNotice&&this.setState({ openNotice:nextProps.openNotice },() => { console.log(this.state.openNotice:nextProps) //将state更新为nextProps,在setState的第二个参数(回调)可以打 印出新的state }) } 2.2.shouldComponentUpdate(nextProps,nextState) 主要用于性能优化(部分更新) 唯一用于控制组件重新渲染的生命周期,由于在react中,setState以后,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新 因为react父组件的重新渲染会导致其所有子组件的重新渲染,这个时候其实我们是不需要所有子组件都跟着重新渲染的,因此需要在子组件的该生命周期中做判断 2.3.componentWillUpdate (nextProps,nextState) shouldComponentUpdate返回true以后,组件进入重新渲染的流程,进入componentWillUpdate,这里同样可以拿到nextProps和nextState。 2.4.componentDidUpdate(prevProps,prevState) 组件更新完毕后,react只会在第一次初始化成功会进入componentDidmount,之后每次重新渲染后都会进入这个生命周期,这里可以拿到prevProps和prevState,即更新前的props和state。 2.5.render() render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。经过比较,我个人觉得做登录拦截应该放在src/pages/Home/Home.js组件中的componentWillMount这个生命周期中,当Home这个组件进行将要挂载时进行判断是否应登录,如果没有登录则需要跳转到登录页面!
如果需要判断当前路由信息与跳转操作,则需要路由组件的API支持,那么如何在Home组件的生命周期中获取到路由组件的支持呢,则需要在对Home组件渲染的时候将路由信息传入到组件中 上代码:src/router/index.js改造后
import React from 'react' import {BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom' import {createBrowserHistory} from 'history' import routes from './route' class IRouter extends React.Component{ constructor(props){ super(props); var hisotry = createBrowserHistory(); console.log(hisotry); hisotry.listen((location, action) => { console.log(action, location, 'listen'); }) } render(){ return ( <Router> <Switch> {/* 开始改造 */} { routes.map((router, key) => { if(undefined !== router.children && router.children.length){ return (<Route key={key} path={router.path} router={router} exact={router.exact} component={props => { return (<router.component {...props} router={router}> { router.children.map((children, key2) => { return <Route path={children.path} key={key2} router={children} exact={children.exact} component={ props => <children.component {...props} router={children} />} /> }) } </router.component>) }} />) }else{ //重点修改部分 component改成props => <router.component {...props} router={router} />} return (<Route key={key} path={router.path} exact={router.exact} component={ props => <router.component {...props} router={router} />}/>) } }) } </Switch> <li><Link to="/">Home</Link></li> <li><Link to="/login" >Login</Link></li> <li><Link to="/board" >board</Link></li> </Router> ) } } export default IRouter然后在Home组件中进行接收与判断跳转等操作
import React from 'react' class Home extends React.Component{ constructor(props){ super(props); this.state = {} } componentDidUpdate(e){ console.log('componentDidUpdate') } componentWillMount(e){ let {history , router, location} = this.props; //history router location console.log(history, router, location); //这里可以看下当前路由信息 if(true){ //在这里做自己的登录判断 history.push('/login'); //这里是跳转 } } shouldComponentUpdate(){ console.log('shouldComponentUpdate') return true; } render(){ return ( <div> This is Home Layout {/* 这里是嵌套页面 */} {this.props.children} </div> ) } } export default Home;这样路由的登录拦截就可以实现了,至于对权限判断的拦截 我觉得可以放在 Home中的shouldComponentUpdate生命周期进行判断,方法类似。 接下来开始学习ReactJs全家桶中的Redux~
