4. 模块边界划分:权限层、UI层、状态层职责边界与依赖关系
在传统前端架构中,权限判断逻辑往往直接嵌入UI组件内部,导致“只要改权限,UI渲染也得跟着测”。State Hoisting 的核心价值在于通过提升共享状态,在权限层(Decision Layer)、状态层(State Layer)、UI层(Presentation Layer)之间建立清晰的模块边界。本章定义这三层的职责边界、依赖方向与数据流契约,并为后续章节的落地提供分层基准。
4.1 三层职责一览
| 维度 | 权限层 (Permission Layer) | 状态层 (State Layer) | UI层 (UI Layer) |
|---|---|---|---|
| 核心职责 | 权限策略定义、用户角色判定、权限计算结果输出 | 权限状态持有、状态提升管理、选择性下发 | 根据传入状态渲染视图、绑定交互事件 |
| 输出 | 权限枚举或布尔值集合(如 canDelete、role) |
注入到UI组件的Props / Context | DOM 树与用户界面 |
| 对UI的感知 | 零感知 | 仅感知组件标识(Component ID),不感知渲染细节 | 零权限逻辑 |
| 依赖关系 | 依赖后端API或本地权限规则 | 依赖权限层输出,提供状态至UI层 | 仅依赖状态层提供的Props |
| 变更影响面 | 权限策略修改,仅影响状态层计算结果 | 状态消费方式变更,影响UI层入参 | UI样式或组件结构修改,不影响权限策略 |
4.2 依赖关系与信任链路
三层之间遵守严格的单向依赖原则:
- 权限层 → 状态层:权限层计算完成后,将结果推送或写入状态层。状态层不反向查询权限策略。
- 状态层 → UI层:UI组件通过 Props 或 Context 接收状态层下发的权限状态。UI组件禁止直接 import 权限工具函数或调用权限 API。
- UI层 ↛ 权限层:这是核心约束——UI组件内部不应出现
if (userHasRole('admin'))这类调用。
常见违规场景:在
useEffect 中调用权限 API,然后根据返回结果 setState 控制按钮显隐。这会导致 UI组件与权限服务产生运行时耦合,任何权限策略调整都需要检索所有涉及该 API 的 UI 组件。
信任链路:状态层是唯一的“信任中介”。UI 组件信任传入的
props.canDelete,无需也不应自行校验该值的来源。这降低了 UI 测试的复杂度——只需验证传入不同 Props 时的渲染结果。
4.3 数据流与控制流描述
- 权限层执行:在应用初始化或用户切换时,权限层(如 PermissionService)通过角色/策略计算出当前用户的权限快照(PermissionSnapshot)。
- 状态写入:权限快照被写入状态层(如父组件中的 state,或 Zustand store)。
- 状态提升与传递:状态层通过 State Hoisting 机制,将权限相关的原子状态提升到合适的层级,再通过 Props 传递给下级 UI 组件。
- UI渲染决策:UI 组件根据
props中的权限值决定是否渲染按钮、菜单项或敏感数据区域。
关键控制流变化:传统架构中,控制流是“UI触发→权限校验→UI自更新”。分层后变为“权限层触发→状态层传递→UI被动渲染”。控制权从 UI 内部剥离,转移到上层状态管理者。
4.4 选型权衡:提升到多高层级?
| 提升策略 | 适用场景 | 优点 | 风险 |
|---|---|---|---|
| 局部提升(组件内部父级) | 单个页面内的权限控制 | 改动范围小,易于理解;适合团队规模小的项目 | 跨页面共享困难,重复提升代码 |
| 全局提升(Redux/Zustand) | 多个页面或跨路由共享权限 | 权限状态全局一致;便于日志审计 | 过度提升导致不必要的全局重渲染;状态层复杂度上升 |
| Context 提升(React Context) | 组件树内部局部共享 | 避免 Props 层层透传;上下文清晰 | Context 更新会导致所有消费组件重渲染;须与 useMemo 配合 |
4.5 风险点与落地步骤
风险点:
- 状态层膨胀:将过多权限状态集中在单一状态管理者中,导致状态层逻辑臃肿,难以调试。
- UI 组件残留权限依赖:重构过程中,部分老代码未被清理,仍直接在组件内调用权限工具函数。
- 提升层级错误:权限状态被提升到过高层级,导致无关组件不必要的重渲染。
落地步骤:
- 审计所有 UI 组件:检索
import中是否包含权限工具类、userHasRole等调用。 - 定义权限状态接口:在状态层声明统一的权限 Props 接口(如
PermissionProps)。 - 批量删除组件内权限逻辑:将条件判断外移至父组件或状态服务。
- 实现状态提升:在公共父组件或 Store 中完成权限计算与 Props 传递。
- 集成测试验证:修改权限策略后,只验证状态层的计算逻辑,UI 组件仅验证传入 Props 的渲染结果。
4.6 验收标准
- 单元验收:UI 组件在没有任何权限服务 mock 的情况下,仅通过 Props 即可完成所有用例渲染。
- 集成验收:权限策略变更(如新增角色)后,无需修改任何
.jsx/.tsx文件。 - 重渲染验收:状态层提升后,使用 React DevTools Profiler 确认非相关组件未产生额外渲染。
- 代码扫描验收:全局搜索
userHasRole、checkPermission等关键词,返回结果仅出现在权限层和状态层模块中。