高阶组件鉴权
权限控制
假设现在有这样一个场景:最近有一个新功能要上线,包含了一系列新开发的页面。现在需要对其中几个页面增加白名单功能,如果不在白名单中的用户访问这些页面只进行文案提示,不展示相关业务数据。一周(功能验收完成)后去掉白名单,对全部用户开放。 以上场景中有几个条件:
- 多个页面鉴权:鉴权代码不能重复写在页面组件中;
- 不在白名单用户只进行文案提示:鉴权过程业务数据请求之前;
- 一段时间后去掉白名单:鉴权应该完全与业务解耦,增加或去除鉴权应该最小化影响原有逻辑。
思路:封装鉴权流程,利用高阶组件的条件渲染特性,鉴权失败展示相关文案,鉴权成功则渲染业务组件。由于属性代理和反向继承都可以实现条件渲染,下面我们将使用比较简单的属性代理方式实现的高阶组件来解决问题:
- 对于需要加权限控制的页面,只需要将页面组件作为参数传给高阶组件 AuthWrapper 即可 。
- 通过使用高阶组件,使得鉴权与业务完全解耦,也避免了鉴权失败时多余的业务数据请求,只需要增加/删除少量代码,即可增加/去除用户白名单的控制,原有业务组件的逻辑也不会受到影响 。
import React from 'react';
import { whiteListAuth } from '../lib/utils'; // 鉴权方法
/**
* 白名单权限校验
* @param WrappedComponent
* @returns {AuthWrappedComponent}
* @constructor
*/
function AuthWrapper(WrappedComponent) {
return class AuthWrappedComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
permissionDenied: -1,
};
}
async componentDidMount() {
try {
await whiteListAuth(); // 请求鉴权接口
this.setState({
permissionDenied: 0,
});
} catch (err) {
this.setState({
permissionDenied: 1,
});
}
}
render() {
if (this.state.permissionDenied === -1) {
return null; // 鉴权接口请求未完成
}
if (this.state.permissionDenied) {
return <div>功能即将上线,敬请期待~</div>;
}
return <WrappedComponent {...this.props} />;
}
}
}
export default AuthWrapper;
增加鉴权后的页面:
import React from 'react';
import AuthWrapper from '../components/AuthWrapper';
class Page1 extends React.Component {
componentWillMount() {
// 获取业务数据
}
render() {
// 页面渲染
}
}
// export default Page1
export default AuthWrapper(Page1);
只需要增加/删除一行代码,改动一行代码,即可增加/去除白名单的控制。
基于路由鉴权
可以根据react-router-config来做 参考:https://juejin.im/post/5d6352116fb9a06ae8361932#heading-15