自定义元素命名必须含短横线且全小写,如date-picker;constructor仅调super()和attachshadow,dom操作移至connectedcallback;样式须注入shadowroot;customelements.define需dom就绪后执行。

自定义元素命名必须含短横线且全小写
浏览器注册时直接拒绝不合规名称,mybutton、MyButton、userprofile都会抛出DOMException: The name "xxx" is not a valid custom element name。只有date-picker、status-badge、nav-menu这类带 ASCII 短横线且全小写的才被接受。
这不是风格建议,是硬性校验:调用customElements.define()瞬间失败,组件根本不会进入初始化流程。别指望try/catch兜底——错误发生在注册阶段,后续逻辑压根没机会执行。
禁止使用下划线(my_button)、大写字母(UserCard)、单个单词(button),也禁止与原生标签重名(div、slot、template等);还要避开html-、svg-、math-等保留前缀。
constructor里只能调super()和attachShadow,DOM操作必须移进connectedCallback
很多人在constructor里写this.innerHTML = ''或this.getAttribute('value'),结果发现属性读不到、样式不生效、this.shadowRoot是null。这是因为constructor执行时元素还没挂载到文档,DOM 上下文不可用。
正确分工是:
-
constructor只做三件事:调super()、调this.attachShadow({ mode: 'open' })(如需 Shadow DOM)、初始化私有字段或绑定方法 - 所有 DOM 查询(
this.shadowRoot.querySelector)、属性读取(this.getAttribute('label'))、事件监听(this.shadowRoot.addEventListener)、模板渲染,都必须放在connectedCallback里 -
attributeChangedCallback不会触发初始属性值,首次渲染仍得在connectedCallback里手动读取 - 如果组件可能被多次挂载/卸载(比如路由切换),
disconnectedCallback要清理定时器和事件监听器,否则内存泄漏
样式必须注入shadowRoot,不能靠外部CSS或@import
把<link rel="stylesheet">写在自定义元素内部,或者用@import加载外部样式,在 Shadow DOM 里基本无效。Shadow DOM 的样式隔离机制决定了:样式必须显式注入this.shadowRoot。
最稳妥的做法是在connectedCallback中拼接<style></style>字符串并插入shadowRoot。例如:
const style = document.createElement('style');
style.textContent = `:host { display: inline-block; } .input { border: 1px solid #ccc; }`;
this.shadowRoot.appendChild(style);
如果样式复杂,可预编译为字符串常量,避免运行时重复解析;想让外部控制尺寸或主题色,要用 CSS 自定义属性配合:host选择器,比如:host([size="large"]) { font-size: 1.2em; }。
customElements.define必须等DOM就绪后执行
脚本放在里同步执行,而<my-card></my-card>标签在里,浏览器解析到这个标签时customElements.define()还没跑,就会当普通未知元素处理——哪怕后面注册成功,也不会自动升级,connectedCallback永远不触发。
✅ 正确做法有两种:
- 用
document.addEventListener('DOMContentLoaded', () => { customElements.define('my-card', MyCard); }); - 用
<script defer></script>包裹注册代码,确保在 HTML 解析完后执行
❌ 千万别写成:<script>customElements.define('my-card', MyCard);</script>放在顶部。动态插入的<script></script>即使加了defer,也不保证执行顺序。
插件式开发里,每个自定义元素都是独立可插拔的单元,但注册时机错一点,整个插件就静默失效——它不会报错,只是不工作,排查起来特别隐蔽。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











