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; // 簡單不?