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 数据流与控制流描述

  1. 权限层执行:在应用初始化或用户切换时,权限层(如 PermissionService)通过角色/策略计算出当前用户的权限快照(PermissionSnapshot)。
  2. 状态写入:权限快照被写入状态层(如父组件中的 state,或 Zustand store)。
  3. 状态提升与传递:状态层通过 State Hoisting 机制,将权限相关的原子状态提升到合适的层级,再通过 Props 传递给下级 UI 组件。
  4. UI渲染决策:UI 组件根据 props 中的权限值决定是否渲染按钮、菜单项或敏感数据区域。
关键控制流变化:传统架构中,控制流是“UI触发→权限校验→UI自更新”。分层后变为“权限层触发→状态层传递→UI被动渲染”。控制权从 UI 内部剥离,转移到上层状态管理者。

4.4 选型权衡:提升到多高层级?

提升策略 适用场景 优点 风险
局部提升(组件内部父级) 单个页面内的权限控制 改动范围小,易于理解;适合团队规模小的项目 跨页面共享困难,重复提升代码
全局提升(Redux/Zustand) 多个页面或跨路由共享权限 权限状态全局一致;便于日志审计 过度提升导致不必要的全局重渲染;状态层复杂度上升
Context 提升(React Context) 组件树内部局部共享 避免 Props 层层透传;上下文清晰 Context 更新会导致所有消费组件重渲染;须与 useMemo 配合

4.5 风险点与落地步骤

风险点:

  • 状态层膨胀:将过多权限状态集中在单一状态管理者中,导致状态层逻辑臃肿,难以调试。
  • UI 组件残留权限依赖:重构过程中,部分老代码未被清理,仍直接在组件内调用权限工具函数。
  • 提升层级错误:权限状态被提升到过高层级,导致无关组件不必要的重渲染。

落地步骤:

  1. 审计所有 UI 组件:检索 import 中是否包含权限工具类、userHasRole 等调用。
  2. 定义权限状态接口:在状态层声明统一的权限 Props 接口(如 PermissionProps)。
  3. 批量删除组件内权限逻辑:将条件判断外移至父组件或状态服务。
  4. 实现状态提升:在公共父组件或 Store 中完成权限计算与 Props 传递。
  5. 集成测试验证:修改权限策略后,只验证状态层的计算逻辑,UI 组件仅验证传入 Props 的渲染结果。

4.6 验收标准

  • 单元验收:UI 组件在没有任何权限服务 mock 的情况下,仅通过 Props 即可完成所有用例渲染。
  • 集成验收:权限策略变更(如新增角色)后,无需修改任何 .jsx / .tsx 文件。
  • 重渲染验收:状态层提升后,使用 React DevTools Profiler 确认非相关组件未产生额外渲染。
  • 代码扫描验收:全局搜索 userHasRole、checkPermission 等关键词,返回结果仅出现在权限层和状态层模块中。

4.7 三层边界与依赖关系示意图

三层边界与依赖关系(单向数据流) 权限层 PermissionService 角色判定 策略计算 输出: 权限快照 状态层 State Hoisting 持有权限状态 依赖权限层 Props / Context 下发 UI 层 纯展示组件 接收 Props 条件渲染 无权限依赖 禁止:UI 层直接依赖权限层 信任链路说明 UI 组件无条件信任状态层传入的 Props,不对其做二次权限校验