Demo/ node_modules/ dist/ src/ components/ MyInput/ index.js // 公共组件,input HOCAuth/ index.js // 核心权限校验组件 pages/ test/ index.js // 咱们的测试页面 model.js // test页面的状态 home/ index.js // home 页面 model.js // home 页面的状态 models/ global.js // 最顶层的全局公共状态 services/ // api等等 utils/ app.js // 入口函数 router.js // 路由配置 package.json ...等等
如何校验权限?
咱们将须要校验的(按钮或页面等)目标组件,经过一个公共组件包裹(即hoc组件),在这个hoc组件中判断目标组件的权限编码是否存在于权限表里,「若存在」则当前有权限访问,渲染。「不存在」则返回 null
。node
那么,咱们首先要储存一份权限表,供全部组件使用。再为每一个组件设置对于的权限编码。react
这里咱们对页面的权限编码配置规则为 '数字-数字',如:'1-2'、'1-3'等等。页面级组件使用'-'链接。
按钮级的权限编码为:'1-1_1'、'1-1_2'等等。 按钮级组件使用'_'链接。
如咱们当前 test
页面编码为 '1-1',且该下面也有两个按钮级组件,那么该组件编码分别为 '1-1_1'、'1-1_2'。json
例子:
const auth = { '1-1': true, '1-1_1': true } // 权限表 const testPageAuthKey = '1-1' // test页面的权限编码 const inputAuthKey = '1-1_1' // test页面下的input组件权限编码 若 auth[authKey] === true 即有权限,渲染对应组件
接下来定义状态:redux
每一个页面有单独的 model.js
(即redux中的store),用于存放该页面的状态。global.js
存放项目最顶层的状态,为公共状态。api
global
中储存一份权限表 auth
,为全部按钮或页面的权限。渲染按钮或页面前,校验当前是否有权限,无权限则返回 null
。app
例子
// global.js const Model = { namespace: 'Global', state: { auth: { '1-1': true, // 表示拥有test页面权限 '1-1_1': true, // 表示拥有test页面下的input组件权限 } // 当前全部的权限 }, effects: { * fetchAuth({ payload, callback }, { call, put }) { // 登陆后调用api获取当前用户所拥有的权限配置,更新掉auth const { auth } = yield call(apiFetchAuthFromServe, payload) yield put({ type: 'save', payload: { auth }, }); if (callback) callback(); } }, reducers: { save (state, { payload }) { return { ...state, ...payload, } }; }, }
components/MyInput/index.js,input组件函数
import React, { useRef, useMemo, memo } from 'react'; import HOCAuth from '../HOCAuth'; const Input = props => { const { onChange, value, defaultValue, } = props; const input = useRef(null); const cur = useMemo(() => { if (value) return value; if (defaultValue) return defaultValue; }, [defaultValue, value]); function onInputChange (e) { if (onChange) onChange(e.target.value); } return ( <input type="text" ref={ input } defaultValue={ cur } onChange={ onInputChange }/> ); }; export default memo(HOCAuth(Input)); // 这里使用HOCAUth包裹 Input
再看看使用:测试
// test/index.js test页面 import React from 'react'; import { connect } from 'dva'; import HOCAuth from '@/components/HOCAuth' import MyInput from '@/components/MyInput' const Test = props => { console.log(props) return ( <div> <MyInput defaultValue={ 'default' } auth={ props.Global.auth } authKey={ '1-1_1' } /> // 传递authKey,表示该组件对应的权限编码 </div> ); }; function mapStateToProps ({ Global, Test }) { return { auth: Global.auth, // 订阅global.js中的auth authKey: Test.authKey, // 当前test页面的权限编码,从model中获取 Test, // test/model.js Global }; } export default connect(mapStateToProps)(HOCAuth(Test)) // 这是页面级的权限校验,使用 HOCAuth 包裹 Test // test/model.js const Model = { namespace: 'Test', state: { authKey: '1-1', // 当前test页面的权限编码 }, ...略 }
接下来是咱们的核心组件HOCAuth,components/HOCAuth/index.jsfetch
import React from 'react'; const HOCAuth = BaseComponent => (props) => { const { auth, authKey, ...others } = props; if (!auth || !authKey) return null; return ( auth[authKey] ? <BaseComponent { ...others }/> : null // 过滤掉 auth与authKey ); }; export default HOCAuth; // 简单不?