必须为class和id添加组件级前缀以避免冲突,如class="user-profile__avatar"、id="user-profile-submit-btn",并配合BEM规范、localStorage前缀隔离、自定义事件命名空间及IIFE封装第三方代码,实现全链路隔离。

class 和 id 必须带组件级前缀,否则必然撞车
HTML 没有原生模块作用域,class="modal" 或 id="submit-btn" 这类泛化名,在多个团队、多个组件共存时,100% 会覆盖或误选。BEM 是当前最轻量、可落地的解法:
根元素用唯一 block 名:class="user-profile",不是 class="profile";
子元素严格双下划线:class="user-profile__avatar",不写成 user-profile-avatar(易与其它连字符命名混淆);
状态修饰符用双短横:class="user-profile--loading",避免 is-loading 这种无归属的状态名。
禁止用样式描述命名,比如 class="big-red-text"——主题换掉就失效;class="user-profile__heading" 才可持续。
localStorage 键必须拼接业务前缀,不能靠“别人别乱写”来防御
localStorage 是纯全局键值对,setItem("theme", "dark") 和第三方脚本写同名 key 会直接覆盖。必须主动隔离:
项目启动时定义常量:const STORAGE_PREFIX = "myapp_v3_user-profile_";
所有读写强制走前缀:localStorage.setItem(`${STORAGE_PREFIX}last-viewed`, "2026-05-01");
封装成工具函数或类,调用时只传逻辑键名,避免手动拼错
不推荐把多个字段塞进单个 key(如 "user-state"),否则更新一个字段就得重写整个对象,增加竞态风险
自定义事件和全局变量必须加组件标识,监听器互相污染是上线必现问题
发 new CustomEvent("submit"),其他任意组件监听同名事件就会误收;挂 window.initWidget 也可能被覆盖。
事件类型加冒号分隔的组件标识:"user-profile:submit"、"user-profile:load-error"(冒号比连字符更易区分层级)
全局变量全包进命名空间对象:window.UserProfile = { init(), destroy(), config: {} };,而不是零散挂 window.init 或 window.userConfig
插入第三方代码片段时,用 IIFE 包裹:(function() { /* 私有变量和函数 */ })();,这是安全兜底
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
CSS 和 JS 的隔离边界必须对齐,否则隔离形同虚设
只改 class 名但 JS 还用 document.getElementById("modal"),或 CSS 写了 .user-profile__header 但 HTML 漏了根节点 class,冲突就从“可能”变成“必然”。
JS 初始化时只查找组件根节点下的后代:rootEl.querySelector(".user-profile__submit-btn")
根元素必须有唯一 block class,且所有子元素、状态类都严格遵循 BEM 规则
如果用了 Shadow DOM,JS 和 CSS 的作用域自然对齐;没用的话,人为约定就是唯一防线——而这条线一旦被跨过,就没有回旋余地
立即学习“前端免费学习笔记(深入)”;


















