HTML自定义标签名必须含破折号,因规范强制要求以此区分用户元素与未来原生标签;不带破折号(如mytag)注册会抛DOMException;前缀(如shop-)属协作约定,非语法强制;注册须早于标签使用,否则需手动upgrade。

HTML 本身没有命名空间机制,所谓“命名空间”在 HTML 中实际是靠自定义标签名的语法约束和注册行为来模拟隔离效果;自定义标签必须含破折号(-),否则 customElements.define() 会直接抛错。
为什么自定义标签名必须带破折号
这是 HTML 规范硬性要求:浏览器通过破折号识别“用户定义元素”,避免与未来可能被标准化的原生标签冲突。不带破折号的名如 mytag 或 tabs 无法注册,调用 customElements.define('mytag', ...) 时会抛出 DOMException: The element name is not valid。
常见错误现象:
- 开发时写了
class MyTag extends HTMLElement { ... },但注册用customElements.define('mytag', MyTag)→ 报错 - 复制示例代码时漏掉破折号,比如把
my-greeting写成mygreeting - 用下划线或驼峰,如
my_greeting、myGreeting→ 同样不合法
自定义标签与 class/id 命名规范不能混用
自定义标签名(如 my-button)和普通 class 或 id 的命名逻辑完全不同:前者是全局注册的 DOM 类型,后者是样式/脚本操作的标识符。它们共用 kebab-case,但语义层级不同。
立即学习“前端免费学习笔记(深入)”;
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
容易踩的坑:
- 把自定义标签当 class 用:
<div class="my-button"> → 实际应写 <code><my-button></my-button>,否则不会触发组件逻辑 - 给自定义标签加冗余 class:
<my-button class="btn-primary"></my-button>→ 可以,但btn-primary是样式类,和my-button的功能无关,别指望它自动继承按钮行为 - 在 JS 中用
document.querySelector('my-button')正常,但若写成document.querySelector('.my-button')就查不到——除非你真给它加了那个 class - 前缀需简短、项目唯一,且全小写,例如
shop-、dash-,避免myapp_v2_这类易变长名 - 一旦注册,
customElements.get('shop-button')能取到构造函数,但customElements.get('button')永远是undefined(原生button不走这个 API) - 不要依赖前缀做运行时判断,比如在
connectedCallback里解析标签名来分支逻辑——这会让组件耦合标签字符串,违背封装原则
多个自定义标签之间的“隐式命名空间”靠前缀隔离
HTML 没有模块级命名空间,但团队实践中常用前缀(如 abc-button、abc-modal)来避免跨项目冲突。这个前缀不是语法要求,而是协作约定。
关键点:
真正容易被忽略的是:自定义标签的注册时机。如果脚本在 DOM 解析完成前执行,customElements.define() 没问题;但如果延迟加载或动态插入,而对应标签已在 HTML 中存在(比如 SSR 渲染出的 <shop-product></shop-product>),这些节点不会自动升级,必须等定义后手动调用 customElements.upgrade(),否则生命周期钩子不触发。


















