最近一直在写一个React、Redux的前端项目,登陆状态验证这一块仍是比较头疼的。前端
个人实践下有三种方式来验证用户登陆状态,目前我选择用三种方式一块儿用在项目里面。json
Redux高阶函数验证(High-Order Function)函数
Actions中间件验证性能
Component WillMount 验证fetch
之因此用三种方式一块儿是由于Redux高阶函数在性能调优的时候并非特别容易。ui
//把须要登陆状态验证的Component传入到这个高阶函数中 export function requireAuthentication(Component) { class AuthenticatedComponent extends Component { constructor(props) { super(props) } //只在首次Mount时来验证权限 componentWillMount() { this.checkAuth(); } checkAuth(){ const {path,isSignIn,dispatch}=this.props; if(!isSignIn){ //没有登陆 //记录当前页面path //跳转到SignIn Page处理登陆 登陆完成够会跳回当前页面 dispatch(CommonActions.setNextUrl(path)) browserHistory.push('/sign'); } } render() { console.log('auth render') return ( <div> {this.props.isSignIn == true ? <Component {...this.props}/> : null } </div> ) } } const mapStateToProps = (state) => ({ path:state.routing.locationBeforeTransitions.pathname, isSignIn:state.common.isSignIn, state:state }) return connect(mapStateToProps)(AuthenticatedComponent); }
你能够把它像这样用在router中:this
{ path:'courseCate',component:requireAuthentication(CourseCate)}
目前存在的一些问题:url
高阶函数中传入的最顶层的Component不能再使用connectspa
过多的高阶函数生命周期的逻辑难以维护、性能隐患code
export function checkAuth(nextUrl,nextFn) { return (dispatch,getState)=>{ //检测用户登陆状况 if(!getState().common.isSignIn){ //没有登陆 记录当前path //跳转到sign page 登陆完成后 跳转回来 dispatch(setNextUrl(nextUrl)); pushUrl('/sign');//封装了 browserHistory.push(url) }else{ //经过验证后 执行下一个Fn dispatch(nextFn); } } }
你能够像这样用在你的Actions中
export function fetchFoo(url,conf) { return (dispatch,getState) => { if(shouldFetchFoo(getState())){ dispatch(requestFetchFoo()); return fetch(url,conf) .then(res=>res.json()) .then(json=>{ ... }) } } } export function needFetchFoo(nextUrl,url,conf){ retrun (dispatch)=>{ dispatch(checkAuth(nextUrl,fetchFoo(url,conf))) } }
目前存在的一些问题:
虽然能够避免过多的高阶函数函数致使页面性能降低,可是没法很好知足业务逻辑
验证若是未经过直接阻断当前操做
这基本上能够认为是Actions中间验证的一种变种
export function checkAuthWithoutNextFn(nextUrl) { return (dispatch,getState)=>{ //check if user sign in if(!getState().common.isSignIn){ //if not set the nexturl //and push url to sign page dispatch(setNextUrl(nextUrl)); pushUrl('/sign'); } } }
你能够像这样把他用在Component WillMount事件中
componentWillMount(){ const {dispatch} = this.props; dispatch(CommonActions.checkAuthWithoutNextFn('/coursecate')); }
目前存在的一些问题:
权限未获得验证时,不会阻断子控件渲染,触发子控件生命周期中的事件
举个例子:
好比父控件中componetWillDidMount中调用该方法判断用户登陆状态
fatherComponet.js
componentWillMount(){ const {dispatch} = this.props; dispatch(CommonActions.checkAuthWithoutNextFn('/coursecate')); }
然而子控件componentWillMount中有一个fetch是须要权限验证(此时父控件中并无阻断子控件渲染,在父控件正在验证权限的同时,子控件的fetch执行了。高阶函数能够阻断子控件渲染)的。
虽然渲染顺序是fatherComponet->childComponet
可是childComponet里的componentWillMount也是触发了(也就是说,在未验证登陆状况下就触发了fetch),可能会形成一些没必要要的请求。
我目前的处理方式:在子控件ComponentWillMount的fetch中加入一个shouldFetch()进行请求前判断。
1.高阶函数适合用在:子控件须要肯定权限后渲染
2.actions中间件适合:无状态页面中的登陆状态判断
3.component验证,使用范围就比较狭窄了。
你们雨露均沾
以上是我我的目前的一些小看法,欢迎各位指正和补充哈。