美文网首页
RouterGuard with react-router5

RouterGuard with react-router5

作者: baxiamali | 来源:发表于2021-06-09 15:25 被阅读0次

作用

  • 阻止页面越权
  • 不用调用接口即可阻止页面越权
    例如:某普通管理员登录,即使知道超管的页面路由地址,也看不到越权的页面。

实现

参考reactrouter官方教程,结合路由嵌套配置,和路由鉴权示例。

https://reactrouter.com/web/example/auth-workflow
https://reactrouter.com/web/example/route-config

代码

  1. router.js 路由配置(增加权限字段)
import MainPart from '../pages/Layout/MainPart';
import Login from '../pages/login/Index.jsx';
import LiveList from '../pages/LiveList/Index.jsx';
import Authority from '../pages/Authority/Index.jsx';
import LiveDetail from '../pages/LiveDetail/Index.jsx';
export default [
        {
            path: '/',
            component: Login,
            exact: true
        },
        {
            path: '/login',
            component: Login
        },
        {
            component: MainPart,
            routes: [
                {
                    path: '/authority',
                    component: Authority,
                    auth:[99,98]
                },
                {
                    path: '/liveList',
                    component: LiveList,
                    auth:[97,98,99]
                },
                {
                    path: '/liveDetail',
                    component: LiveDetail,
                },
            ]
        },
];
  1. index.js 引入<RouterGuard>组件
import React, {useReducer,Fragment } from 'react';
import {HashRouter as Router, Route, Switch,Redirect, } from 'react-router-dom';
import ReactDom from 'react-dom';
import routers from './router';
import {defaultState, reducer, COMMON_CONTEXT} from './COMMON/store';
import RouterGuard from './RouterGuard.js';


function Index() {
    const [state, dispatch] = useReducer(reducer, defaultState);
    return (
        <COMMON_CONTEXT.Provider value={{state, dispatch}}>
            <Router>
                <Switch>
                    {routers.map((route, i) => (
                        <RouterGuard key={i} {...route} />
                    ))}
                </Switch>
            </Router>
        </COMMON_CONTEXT.Provider>);
}

document.title = '和家亲直播能力平台';
ReactDom.render(<Index/>, document.querySelector('#app'));
  1. RouterGuard.js 增加拦截逻辑
function RouterGuard(route) {
  const {state} = useContext(COMMON_CONTEXT);
  console.log(state);
  return (
    
    <Route
        path={route.path}
        render={props => (
          route.auth?.indexOf(Number(state.authCode))==-1?
          <Redirect
            to={{
              pathname: "/login",
            }}
          />:
          <route.component {...props} routes={route.routes} />
        )}
      />
    );
  }
  
  export default RouterGuard;
  1. 嵌套路由处理
            <Layout className="m-content" >
                <HeaderMenu />
                <Content>
                    <Switch>
                        {routes.map((route, i) => (
                            <RouterGuard key={i} {...route} />
                        ))}
                    </Switch>
                </Content>
            </Layout>
  1. 登录后,保存权限配置
const {dispatch} = useContext(COMMON_CONTEXT);
const function loginApi=()=>{
        //省略登录逻辑代码
        dispatch({
                authToken,
                authUserCode: userCode,
                authCode,
                authRole,
                authPhone
            });
}

HOOKS 相关知识点

useContext与useReducer 代替 redux

  1. useContext

const value = useContext(MyContext);
接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。
当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext provider 的 context value 值。

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}
  1. useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init);

useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。(如果你熟悉 Redux 的话,就已经知道它如何工作了。)

在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数

以下是用 reducer 重写 useState 一节的计数器示例:

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

相关文章

  • RouterGuard with react-router5

    作用 阻止页面越权 不用调用接口即可阻止页面越权例如:某普通管理员登录,即使知道超管的页面路由地址,也看不到越权的...

网友评论

      本文标题:RouterGuard with react-router5

      本文链接:https://www.haomeiwen.com/subject/gijjeltx.html