自定义元素不自动解决命名冲突,需严格遵循破折号规则、注册时机和前缀约定:标签名必须含破折号(如shop-button),注册须早于dom解析,前缀应全小写且项目唯一;否则将退化为普通标签。

自定义元素本身不解决 DOM 节点命名冲突,它只提供一种**隔离命名空间的机制**——但前提是严格遵循破折号规则、注册时机和前缀约定,否则反而会制造新冲突。
customElements.define() 报错 "The element name is not valid"
这是最常卡住的第一步。浏览器在 customElements.define() 时直接校验标签名格式,不是警告,是硬性拒绝:
-
mybutton、MyButton、my_button全部非法,立刻抛DOMException: The element name is not valid - 漏掉破折号往往源于复制示例时手误,比如把
shop-button写成shopbutton <div class="shop-button"> 不会报错,但也不会触发组件逻辑——它只是普通 div,别把它当自定义元素用 <h3>多个团队共用同一页面时,<code>shop-button和dash-button还是会撞车吗不会,只要前缀不同且都含破折号,就天然隔离。但“前缀”不是语法强制,而是协作底线:
- 原生
button永远不会被customElements.get('button')返回,它不走这套注册机制 - 前缀必须全小写、固定长度、项目/组织级唯一,比如
shop-、dash-,避免myapp_v2_这类易变长难维护的格式 - 别在组件内部靠
this.localName.includes('shop-')做逻辑分支——这会让组件耦合字符串,破坏封装
<shop-button></shop-button>渲染出来却没生效,连 shadow DOM 都没挂上大概率是注册晚于 DOM 解析。HTML 解析器遇到未知标签(如
<shop-button></shop-button>)会当成 void 元素处理,之后再define也无法自动升级:- 确保脚本在
之前执行,或用<script type="module"></script>(默认 defer) - 如果已渲染,必须手动调用
customElements.upgrade(document.body)或针对单个节点customElements.upgrade(el) - 别等
DOMContentLoaded再注册——此时部分标签可能已被解析,风险不可控
想用
setAttributeNS给自定义元素加命名空间属性来进一步隔离?别试。HTML 环境中
setAttributeNS是无效操作:-
el.setAttributeNS("http://example.com/ns", "ns:foo", "bar")插入 DOM 后,ns:foo会被浏览器直接剥离成foo,xmlns:ns也消失 - 这不是 Bug,是 Blink/WebKit 的明确行为;XML 命名空间只在
DOMParser解析 XML 时有效 - 真正需要属性隔离,统一用
data-前缀:data-shop-theme、data-dash-version,读取时用el.getAttribute('data-shop-theme')
破折号是铁律,前缀是契约,注册时机是开关——三者缺一,自定义元素就退化成普通标签,所谓“命名空间隔离”也就无从谈起。
- 原生











