前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库自定义元素 命名规则 连字符
HTML语义与文档

自定义元素名为什么一定要有连字符?

注册自定义元素时,名称必须以 ASCII 小写字母开头,并包含连字符,例如 user-card;不能写成 UserCard 或 usercard。连字符为作者自定义名称留出独立空间,使将来新增的原生 HTML 标签不会和现有组件撞名。

前端进阶之旅 · 一题精讲更新于 2026.09.29
HTML#语义与文档
先看核心答案读代码示例
理解线索

浏览器怎样识别自定义标签

  1. 合法名称如 user-card,以小写字母开头并含连字符
  2. 命名空间连字符把作者标签与标准元素名称区分开
  3. 注册表customElements.define() 将名称与类关联

user-card 合法不代表已经有行为;未注册前它只是一个尚待升级的自定义元素。

核心回答

先记住这个答案

自定义元素名必须以 ASCII 小写字母开头,至少包含一个连字符,且不能含 ASCII 大写字母;还要避开规范保留的少数名称。user-card 是常见的合法写法,usercard、UserCard 不行。连字符让浏览器把作者定义的标签与标准元素分开,HTML、SVG 或 MathML 将来新增标准标签时,就不会占用作者已有的名称。

  • 名称须以 ASCII 小写字母开头
  • 名称必须包含连字符,不能含 ASCII 大写字母
  • 少数规范保留的连字符名称也不能用
  • 同一注册表中不能重复注册同名元素

从注册一个卡片组件看命名

组件名不是随便写在 HTML 里的字符串。调用 customElements.define() 时,浏览器会检查名称是否合法,再把它和构造类关联起来。模板里已有同名标签时,注册后这些元素可以被升级为对应组件。

注册独立自定义元素JavaScript
class UserCard extends HTMLElement {
  connectedCallback() {
    this.textContent = '用户资料' // 元素接入文档时填入内容
  }
}
customElements.define('user-card', UserCard)
// HTML 中可使用 <user-card></user-card>

UserCard 是 JavaScript 类名,可以按类命名习惯首字母大写;真正传给 define() 的标签名必须是小写且带连字符。把类名与标签名混为一谈,是面试里常见的失误。元素定义后,document.createElement('user-card') 和 HTML 中的 <user-card> 都可以创建它。

连字符解决什么冲突

浏览器需要区分“目前不认识、但未来可能成为标准的标签”和“开发者明确要注册的标签”。如果允许自定义元素直接叫 card,未来标准库加入 <card> 时,旧网站和新标准就会争夺同一个名字。要求连字符,相当于为作者保留一块不会被标准元素占用的命名空间。

但带连字符还不够。名称必须以 ASCII 小写字母开头,不得包含 ASCII 大写字母;规范还保留了例如 annotation-xml 和 font-face 等少数已有用途的名称。不要只靠“有横杠”判断是否合法。构建团队组件库时,通常再加统一前缀,如 acme-user-card,降低不同库在同一页面内注册同名元素的概率。

命名错误和重复注册不是一回事

如果传入的名字不符合有效自定义元素名规则,define() 会因名字无效抛异常。如果名字合法,但同一注册表已经注册过这个名字,或构造器已被注册,也会失败;这是注册冲突,换成另一个合法名字或检查初始化代码是否重复执行。热更新环境尤其容易遇到后一种情况,先用 customElements.get('user-card') 看看是否已注册,再决定是否调用 define()。

命名合法也不自动提供原生按钮、输入框等行为。独立自定义元素继承的是 HTMLElement,若做可交互控件,还需认真处理键盘、焦点、状态、表单和无障碍语义。能直接用原生元素满足需求时,不必为了“组件化”而新造标签。

回答前,多想一步

容易答错的地方

以为 JavaScript 类名也必须带连字符
类名可以是 UserCard;带连字符的要求针对注册名称和 HTML 标签名。customElements.define('user-card', UserCard) 正是两种命名同时出现的正常写法。
以为任何带连字符的字符串都有效
首字符、ASCII 大写字母和保留名称仍有约束。9-user-card 不能以数字开头;user-Card 含大写字母,也不是有效的自定义元素名。
试着用自己的话回答

面试官还会怎么问?

为什么标签已经写在 HTML 中,后注册也能工作?

浏览器解析时可先创建尚未升级的自定义元素。调用 customElements.define() 注册对应名称后,符合条件的现有元素会升级,随后运行组件的生命周期逻辑。

同名组件能在一个页面注册两次吗?

不能在同一个注册表里对同名元素重复调用 define()。应用初始化、微前端集成或热更新时,要检查是否已注册,避免重复注册异常。

可以直接继承 <button> 的所有行为吗?

那属于“自定义内置元素”的另一条路线,定义时需要声明所扩展的内置标签,使用时也不是普通的 <user-card> 写法。它的支持情况与独立自定义元素不同,实际项目要按目标浏览器验证。

从一道题,走向一组知识

把知识连起来

语义与文档

data-* 适合存什么?屏幕阅读器会读出来吗?

data-* 是给现有元素附加数据;自定义元素则通过新标签名注册独立组件。

语义与文档

datalist 怎么给输入框加候选值?

自定义输入组件若想替代原生 <datalist> 的体验,还需自行考虑键盘和表单行为。

参考资料

  • HTML:语义与文档参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 从注册一个卡片组件看命名
  3. 连字符解决什么冲突
  4. 命名错误和重复注册不是一回事
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑