利用闭包封装私有计数器生成唯一组件id,确保跨组件不冲突且避免全局污染;支持命名空间隔离与ssr适配,禁止在渲染中调用以防重复生成。

在组件库中,用闭包生成自增的唯一组件 ID,核心是**利用闭包保存私有计数器,每次调用工厂函数时返回新 ID**,避免全局变量污染,同时保证跨组件、跨实例不冲突。
闭包封装自增计数器
定义一个立即执行函数(IIFE),内部维护一个私有变量 idCounter,返回一个生成 ID 的函数:
const generateId = (() => {
let idCounter = 0;
return () => `comp-${++idCounter}`;
})();
每次调用 generateId() 都会返回如 comp-1、comp-2 这样的字符串。闭包让 idCounter 不被外部访问,又能在多次调用间持续累加。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
在组件构造逻辑中使用
以类组件或函数组件的初始化为例,ID 应在实例创建时生成,而非渲染时(防止重复触发):
- 类组件:在 constructor 或实例属性初始化时调用
generateId() - 函数组件:在
useMemo或自定义 Hook 内部调用(确保仅初始化一次)
// 示例:自定义 Hook 封装
function useComponentId(prefix = 'comp') {
const id = useMemo(() => `${prefix}-${generateId()}`, [prefix]);
return id;
}
// 组件内使用
function Button() {
const compId = useComponentId('btn');
return <button id="{compId}">Click me</button>;
}
支持命名空间隔离(多组件库共存场景)
若组件库需支持多个独立实例(如微前端中多个版本共存),可扩展闭包为工厂函数,按命名空间隔离计数器:
const createIdGenerator = (namespace = 'default') => {
const counters = new Map();
return () => {
const count = counters.get(namespace) || 0;
counters.set(namespace, count + 1);
return `${namespace}-${count + 1}`;
};
};
// 各组件库使用自己的 generator
const buttonIdGen = createIdGenerator('button');
const inputIdGen = createIdGenerator('input');
注意事项与边界情况
- ID 仅保证**同一运行时内唯一**,服务端渲染(SSR)时需注意:若组件在服务端和客户端分别生成 ID,可能导致 hydration mismatch;建议 SSR 时统一由服务端注入起始值,或禁用服务端 ID 生成
- 避免在 render 函数中直接调用生成函数(如
{generateId()}),否则每次重渲染都会产生新 ID - 不需要“重置计数器”,除非明确设计多实例隔离 —— 正常组件库生命周期中,全局唯一递增是合理且安全的
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










