自定义元素命名必须含连字符且全小写,如date-picker;DOM操作须在connectedCallback中执行;样式必须注入Shadow DOM;attributeChangedCallback是唯一安全通信出口。

自定义元素命名必须含连字符且全小写
浏览器注册时直接拒绝不合规名称,customElements.define() 会立刻抛出 DOMException: The name "xxx" is not a valid custom element name。这不是警告,是硬性拦截——mybutton、MyButton、userprofile 全部失败。
合法名仅限 ASCII 短横线 + 全小写,例如 date-picker、status-badge、ds-form。下划线(my_button)、大写字母、单个单词(button)都不行;更不能与原生标签重名(div、slot、template 都会报错)。
命名不是风格问题,是接口契约的起点:它决定了团队能否统一引用、工具能否自动识别、Lighthouse 能否校验语义。
DOM 操作必须在 connectedCallback 中执行
constructor 里做 DOM 查询或设置 innerHTML,结果往往是 this.shadowRoot 为 null、属性读不到、样式不生效——因为此时元素还没挂载到文档,没有 DOM 上下文。
立即学习“前端免费学习笔记(深入)”;
正确分工如下:
-
constructor:只调用super()、创建 Shadow DOM(this.attachShadow({ mode: 'open' }))、声明私有字段 -
connectedCallback:读取属性(this.getAttribute('value'))、查询shadowRoot下节点、绑定事件、设置初始内容 -
attributeChangedCallback:仅响应后续变更,首次值需在connectedCallback手动读取
若组件可能被多次挂载(如路由切换),disconnectedCallback 必须清理定时器和事件监听器,否则内存泄漏。
样式必须注入 Shadow DOM,不能靠外部 CSS 或 style 标签
把 <link rel="stylesheet"> 放在自定义元素内部,或在 <style> 块里写规则,基本无效。Shadow DOM 的样式隔离机制决定了:样式必须显式注入 shadowRoot。
两种可靠方式:
- 在
connectedCallback中拼接字符串写入shadowRoot.innerHTML(兼容性好) - 用
adoptedStyleSheets注入CSSStyleSheet实例(现代浏览器支持,可复用样式表)
禁止依赖全局 class 或外部 .css 文件——否则封装失效,样式污染风险极高。极简设计系统中,甚至只允许 :host 控制根状态,所有子元素样式写死在 shadow 内。
attributeChangedCallback 是通信唯一安全出口
父应用传参不能靠 props 或自动类型转换,所有 attribute 都是字符串。传 <date-picker value="2026-06-30"></date-picker>,拿到的是字符串,不是 Date 对象。
因此:
- 复杂配置必须显式解析:
JSON.parse(this.getAttribute('config')),且要加try/catch - 布尔属性(如
disabled)靠是否存在判断,不要读值:this.hasAttribute('disabled') - 通信只能通过 attribute 变更触发
attributeChangedCallback,不能在constructor或connectedCallback里发CustomEvent——接收方很可能还没 ready
跨框架微前端场景下,这是父/子应用间最可控的数据通道;但别忘了在 observedAttributes 中显式声明监听列表,否则回调根本不会触发。



















