customelements.define()只接受带破折号的全小写名称,否则立即抛domexception;浏览器私有前缀与自定义标签名无交集,命名前缀如shop-button仅为协作约定,非语法强制,且注册后无法卸载。

customElements.define() 只接受带破折号的全小写名称,其他形式一律抛 DOMException;浏览器私有扩展(如 -webkit-、-moz-)与自定义标签名无交集,不影响注册,但会影响其内部样式和伪元素控制。
为什么 my-button 合法而 mybutton 不行
这不是风格偏好,是 HTML 规范强制校验:解析器在调用 customElements.define() 时立即检查名称格式。不满足「至少一个 ASCII 破折号 + 全小写 + 不能是原生标签名」三条件,就直接拒绝注册,不会进入组件逻辑。
常见非法写法:
-
mybutton(缺破折号) -
MyButton(含大写) -
my_button(用下划线) -
div或slot(与原生标签重名)
错误信息固定为:DOMException: The element name is not valid。别指望 try/catch 捕获后还能补救——注册失败即组件未定义,后续 document.createElement('mybutton') 会创建普通 HTMLUnknownElement,不触发任何生命周期。
自定义标签内部用 ::-webkit-progress-value 会失效吗
不会失效,但仅限于该伪元素所作用的宿主元素本身。比如你在 my-progress 组件里用 progress::-webkit-progress-value,它只对组件 Shadow DOM 内部的 <progress></progress> 生效;而 my-progress 自身不支持这类伪元素——你不能写 my-progress::-webkit-inner-spin-button,因为浏览器根本不识别这个标签名的私有扩展语义。
真正要注意的是兼容性断层:
-
progress标签的伪元素(如::-moz-progress-bar)在 Firefox 中有效,但在自定义标签内部嵌套的<progress></progress>上仍需单独适配 - 像
input[type="number"]的::-webkit-inner-spin-button这类私有伪类,只绑定到原生标签,无法通过自定义标签名继承或转发 - 不要试图用
my-input::-webkit-inner-spin-button控制样式——它什么都不会匹配
前缀如 shop-button 是命名空间还是协作约定
纯属团队协作约定,HTML 解析器完全无视前缀。浏览器不区分 shop-button 和 my-button,只要含破折号、全小写、不冲突,就都合法。
但它解决的是真实冲突问题:
- 多个 npm 包同时注册
button?不可能,名称必须含破折号 - 两个包都注册
ui-button?会后者覆盖前者,且无警告 - 加前缀如
abc-button、xyz-modal是预防性隔离,不是语法保障
所以前缀要早于发布就定死,且最好和包名/组织名一致;否则上线后改前缀等于 breaking change——所有模板里的 <ui-button></ui-button> 都得手动替换成 <abc-button></abc-button>。
最易被忽略的一点:自定义标签名一旦注册,就全局生效,且无法卸载。哪怕你删了 JS 文件、清空模块缓存,只要页面中曾执行过 customElements.define('my-card', MyCard),后续同名注册就会静默失败,也不会报错提示——它只是跳过。调试时看到组件没反应,第一反应不该是查 JS 错误,而是查是否重复注册或名称拼错。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











