面试题答案
一键面试设计方案
1. 路由配置
在React应用中,使用react-router-dom
库来配置路由。为每个路由添加自定义的权限属性,例如roles
(允许的角色)和departments
(允许的部门)。
import { Routes, Route } from'react-router-dom';
import ParentComponent from './ParentComponent';
import ChildComponent from './ChildComponent';
const routes = (
<Routes>
<Route path="/parent" element={<ParentComponent />}>
<Route
path="child"
element={<ChildComponent />}
roles={['admin', 'editor']}
departments={['tech', 'design']}
/>
</Route>
</Routes>
);
2. 路由守卫
创建一个高阶组件(HOC)作为路由守卫。这个HOC会检查当前用户的角色和部门,与路由配置中的权限属性进行对比。
import { useLocation } from'react-router-dom';
import React from'react';
const withAuth = (WrappedComponent) => {
return (props) => {
const location = useLocation();
const user = { role: 'admin', department: 'tech' }; // 假设从上下文或存储中获取用户信息
const { roles, departments } = location.state || {};
if (roles &&!roles.includes(user.role)) {
// 角色不匹配,重定向到无权限页面
return <Navigate to="/no - permission" replace />;
}
if (departments &&!departments.includes(user.department)) {
// 部门不匹配,重定向到无权限页面
return <Navigate to="/no - permission" replace />;
}
return <WrappedComponent {...props} />;
};
};
export default withAuth;
3. 应用路由守卫
在路由配置中使用路由守卫HOC。
import { Routes, Route } from'react-router-dom';
import ParentComponent from './ParentComponent';
import ChildComponent from './ChildComponent';
import withAuth from './withAuth';
const routes = (
<Routes>
<Route path="/parent" element={<ParentComponent />}>
<Route
path="child"
element={withAuth(<ChildComponent />)}
roles={['admin', 'editor']}
departments={['tech', 'design']}
/>
</Route>
</Routes>
);
4. 可扩展性
- 增加新权限类型:如果需要增加新的权限类型,例如用户的区域限制,可以在路由配置中添加新的属性(如
regions
),并在路由守卫HOC中添加相应的检查逻辑。 - 动态权限加载:可以将权限配置存储在后端,在应用初始化时加载,这样可以在不重新部署应用的情况下更新权限配置。
可能遇到的难点及解决方案
1. 复杂权限逻辑
- 难点:随着应用的发展,权限逻辑可能变得非常复杂,例如需要满足多个条件的组合(如用户角色为admin且部门为tech)。
- 解决方案:可以使用更复杂的权限表达式,例如将权限条件表示为一个函数,在路由守卫中调用这个函数来进行权限检查。
2. 异步权限加载
- 难点:如果权限信息需要从后端异步获取,在路由守卫执行时可能还未获取到权限信息。
- 解决方案:可以使用React的
Suspense
和lazy
加载机制,在应用启动时异步加载权限信息,并在权限信息加载完成后再渲染路由。或者在路由守卫中使用async/await
来等待权限信息的获取。
3. 嵌套路由传递参数
- 难点:在多层嵌套路由中,如何将权限相关的参数准确传递到每个子路由的守卫中。
- 解决方案:通过
location.state
在路由跳转时传递权限相关参数,或者使用上下文(Context)来共享权限信息,这样每个路由守卫都可以访问到所需的权限数据。