Iterator通过生成器实现惰性求值的菜单权限过滤,每次next()仅校验当前节点权限并延迟展开子菜单,配合UI按需消费,避免预计算完整结构。

在动态菜单权限过滤中,Iterator 不是直接“按需生成菜单”,而是提供一种可中断、可复用、惰性求值的遍历机制——它让菜单数据的过滤和展开过程变成可控的流式操作,而不是一次性构建完整结构。
用 Iterator 封装权限过滤逻辑
把菜单原始数据(如树形数组)和权限校验规则封装成一个自定义迭代器,每次调用 next() 才检查当前节点是否可见,跳过无权限项,避免预计算整个过滤后数组。
例如:
function* filterMenuByPermission(menuList, hasPerm) {
for (const item of menuList) {
// 顶层菜单权限校验
if (!hasPerm(item.permission)) continue;
<pre class="brush:php;toolbar:false;">// 惰性处理子菜单:仅当需要时才递归过滤
const filteredChildren = item.children
? [...filterMenuByPermission(item.children, hasPerm)]
: [];
yield { ...item, children: filteredChildren };} }
// 使用 const menuIterator = filterMenuByPermission(rawMenus, userHasPermission); console.log(menuIterator.next().value); // 只算第一个可见菜单项
配合生成器实现深度优先的按需展开
菜单常为嵌套结构,若用户只展开一级,没必要递归校验全部子项。通过生成器函数的递归 + yield*,可让子树迭代延迟到外层真正消费时才触发。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 外层迭代器只 yield 当前层级可见项
- 子菜单不立即执行,而是返回另一个迭代器(
yield* subIterator) - React/Vue 中结合
useMemo或computed缓存迭代结果,避免重复遍历
与 UI 渲染联动:用 Symbol.iterator 实现可遍历菜单对象
将权限过滤后的菜单包装成可迭代对象,使模板语法(如 for...of)天然支持按需消费:
class PermissionMenu {
constructor(menuData, permChecker) {
this.data = menuData;
this.check = permChecker;
}
<p><em>[Symbol.iterator]() {
yield</em> filterMenuByPermission(this.data, this.check);
}
}</p><p>// 在 JSX 或模板中直接使用
for (const item of new PermissionMenu(menus, hasPerm)) {
renderMenuItem(item); // 每次循环才触发一次权限判断和结构构造
}
</p>注意边界:Iterator 本身不管理状态,需配合缓存或闭包保存权限上下文
由于每次调用 next() 是独立的,若权限校验依赖异步(如接口鉴权),就不能用同步生成器。此时应:
- 改用
AsyncIterator(async function*),配合for await...of - 将已校验过的节点缓存在闭包或 WeakMap 中,避免重复请求
- 对高频访问菜单项做记忆化(memoize),如
memoizedCheck = memo(hasPerm)
本质上,Iterator 在这里不是银弹,而是把“权限过滤”从一次性数组映射,转为声明式、可暂停、可组合的数据流——真正实现按需,靠的是生成器的惰性 + 权限判断的时机控制 + UI 层的渐进式消费。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










