customElements.define() 必须传含短横线的合法标签名且类继承 HTMLElement,constructor() 中禁止 DOM 操作;DOM 操作需移至 connectedCallback(),样式须手动注入 adoptedStyleSheets。

customElements.define() 必须传含短横线的合法标签名,否则直接抛 DOMException;类定义必须继承 HTMLElement,且不能在 constructor() 里操作 DOM —— 这两点踩错一个,组件就根本跑不起来。
为什么 customElements.define('mybutton', MyButton) 总报错?
浏览器对自定义元素名有硬性校验:必须含至少一个短横线(-),且不能是单个单词。写成 'mybutton' 或 'MyButton' 都会触发 DOMException: The element name must contain a hyphen。
-
'site-header'✅ 合法;'header'❌ 单词,非法;'myButton'❌ 驼峰命名,但注册时传的字符串必须全小写+短横线 - 传入
null、undefined、已注册过的名称,同样抛DOMException - 注册前加守卫很必要:
if (!customElements.get('site-header')) { customElements.define('site-header', SiteHeader); },尤其在热更新或多次加载脚本时
constructor() 里为什么不能调用 this.innerHTML 或 this.querySelector()?
自定义元素实例化发生在 DOM 解析阶段,此时元素尚未插入文档树,this 虽已存在,但 shadowRoot 还没挂载,DOM 方法调用会失败,报错 Failed to construct 'CustomElement': Please use the 'new' operator。
-
constructor()只做三件事:调用super()、调用this.attachShadow({ mode: 'open' })、设默认属性值 - 所有 DOM 操作(填充模板、绑定事件、发起请求)必须移至
connectedCallback() - 如果组件需响应属性变更,还得配合
static get observedAttributes()和attributeChangedCallback(),否则 HTML 中写的<my-card title="foo"></my-card>不会触发更新
Shadow DOM 里样式为啥不生效?
import './card.css' 在模块中执行只是副作用,浏览器不会自动把 CSS 注入 Shadow DOM。漏掉显式注入步骤,样式要么泄漏到全局,要么完全不显示。
- 必须手动创建
CSSStyleSheet实例:const sheet = new CSSStyleSheet() - 用
sheet.replaceSync(cssText)或await sheet.replace(cssText)加载样式内容(支持从fetch读取) - 再赋值给
this.shadowRoot.adoptedStyleSheets = [sheet];注意这是覆盖式赋值,追加样式得先push()再重新赋值 - 别指望
<style></style>标签在innerHTML里自动生效 —— Shadow DOM 不解析内联<style></style>
怎么让自定义元素真正“按需加载”?
customElements.define() 本身不触发代码分片,它只是注册行为。哪怕页面里根本没出现 <site-header></site-header>,只要执行了这行代码,整个组件 JS 就已下载并解析完毕。
- 真正实现分片,得靠动态
import()+ 类定义分离:组件文件只导出类,入口逻辑负责监听首次使用并动态加载 - 例如在
DOMContentLoaded后检查document.querySelectorAll('site-header'),若存在则import('./site-header.js').then(mod => customElements.define('site-header', mod.SiteHeader)) - 构建工具(如 Vite/Webpack)需配置 code-splitting,否则
import()也只会打包进主 chunk
最常被忽略的不是语法,而是生命周期和样式注入的耦合关系:connectedCallback 和 adoptedStyleSheets 必须配对出现,缺一不可。否则你写的组件看起来“能渲染”,实则随时可能因 DOM 状态或样式时机问题崩掉。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











