MST

星途 面试题库

面试题:React高阶组件权限控制在复杂业务场景中的应用

假设存在一个复杂的企业级应用,包含多角色、多层次的权限体系,如管理员、普通用户、访客等,不同角色对不同模块有不同的读写权限。请详细阐述如何利用React高阶组件设计一个通用且可扩展的权限控制方案,涵盖组件封装、权限数据管理与加载、以及与后端权限验证服务的交互等方面,并给出关键代码片段。
11.3万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

1. 组件封装

  1. 创建高阶组件
    • 高阶组件(HOC)是一个函数,它接受一个组件并返回一个新的组件。这个新组件会增强原组件的功能,在这里是添加权限控制功能。
    import React from'react';
    
    const withPermissions = (requiredPermissions) => {
      return (WrappedComponent) => {
        return (props) => {
          // 这里开始权限检查逻辑
          const hasPermissions = true; // 暂时占位,后续会实现真实逻辑
          if (hasPermissions) {
            return <WrappedComponent {...props} />;
          }
          return null;
        };
      };
    };
    
    export default withPermissions;
    
  2. 使用高阶组件
    • 假设我们有一个需要权限控制的组件SomeProtectedComponent
    import React from'react';
    import withPermissions from './withPermissions';
    
    const SomeProtectedComponent = () => {
      return <div>这是一个需要权限的组件</div>;
    };
    
    const requiredPermissions = ['read:module1', 'write:module1'];
    const ProtectedComponent = withPermissions(requiredPermissions)(SomeProtectedComponent);
    
    export default ProtectedComponent;
    

2. 权限数据管理与加载

  1. 在Redux中管理权限数据
    • 安装reduxreact - redux
    • 创建一个reducer来管理权限数据。
    const initialState = {
      permissions: []
    };
    
    const permissionsReducer = (state = initialState, action) => {
      switch (action.type) {
        case 'SET_PERMISSIONS':
          return {
           ...state,
            permissions: action.payload
          };
        default:
          return state;
      }
    };
    
    export default permissionsReducer;
    
    • 创建一个action来更新权限数据。
    const setPermissions = (permissions) => {
      return {
        type: 'SET_PERMISSIONS',
        payload: permissions
      };
    };
    
    export default setPermissions;
    
    • store中配置reducer
    import { createStore } from'redux';
    import permissionsReducer from './permissionsReducer';
    
    const store = createStore(permissionsReducer);
    
    export default store;
    
  2. 加载权限数据
    • 在应用启动时,可以通过redux - thunk或其他异步中间件从后端加载权限数据。
    import React from'react';
    import ReactDOM from'react - dom';
    import { Provider } from'react - redux';
    import store from './store';
    import setPermissions from './setPermissions';
    import axios from 'axios';
    
    const loadPermissions = async () => {
      try {
        const response = await axios.get('/api/permissions');
        store.dispatch(setPermissions(response.data));
      } catch (error) {
        console.error('加载权限数据失败', error);
      }
    };
    
    loadPermissions();
    
    ReactDOM.render(
      <Provider store = {store}>
        {/* 应用的其余部分 */}
      </Provider>,
      document.getElementById('root')
    );
    

3. 与后端权限验证服务的交互

  1. 前端验证
    • 在高阶组件中利用从后端获取并存储在Redux中的权限数据进行前端验证。
    import React from'react';
    import { useSelector } from'react - redux';
    
    const withPermissions = (requiredPermissions) => {
      return (WrappedComponent) => {
        return (props) => {
          const permissions = useSelector((state) => state.permissions);
          const hasPermissions = requiredPermissions.every((permission) => permissions.includes(permission));
          if (hasPermissions) {
            return <WrappedComponent {...props} />;
          }
          return null;
        };
      };
    };
    
    export default withPermissions;
    
  2. 后端验证
    • 当用户执行某些关键操作时,如保存数据到服务器,前端可以将操作和用户当前权限信息发送到后端。
    import axios from 'axios';
    import { useSelector } from'react - redux';
    
    const performAction = async () => {
      const permissions = useSelector((state) => state.permissions);
      try {
        const response = await axios.post('/api/saveData', {
          data: { /* 要保存的数据 */ },
          permissions
        });
        console.log('操作成功', response.data);
      } catch (error) {
        console.error('操作失败', error);
      }
    };
    
    • 后端接收到请求后,根据其自身的权限验证逻辑验证请求是否合法,并返回相应的结果。例如,在Node.js + Express中:
    const express = require('express');
    const app = express();
    app.use(express.json());
    
    app.post('/api/saveData', (req, res) => {
      const { permissions } = req.body;
      // 这里进行后端权限验证逻辑
      const isValid = true; // 暂时占位,后续实现真实逻辑
      if (isValid) {
        res.json({ message: '数据保存成功' });
      } else {
        res.status(403).json({ message: '权限不足' });
      }
    });
    
    const port = 3001;
    app.listen(port, () => {
      console.log(`服务器在端口 ${port} 上运行`);
    });