is属性仅对button、canvas等规范白名单中的原生标签生效,须配合customelements.define()的{extends:"xxx"}注册;任意标签加is无效,且vue的:is与原生is机制互不兼容。

is 属性只对特定原生标签生效,不是万能“升级开关”
浏览器不会因为你给任意标签加了 is 属性就自动把它变成自定义元素。它只在规范明确允许的原生标签上起作用,比如 button、canvas、table、tr、td、p 等——这些是 WHATWG HTML 标准里白名单里的“可扩展内置元素”。
写 <div is="my-thing"> 或 <code><p is="highlight"></p> 完全无效,解析后仍是普通 HTMLDivElement 或 HTMLParagraphElement,生命周期钩子、自定义行为一概不触发。
必须配合 customElements.define() 的 extends 选项注册
即使你用了支持 is 的标签,也必须用 customElements.define() 显式注册,并传入 { extends: "button" } 这类选项,否则 is 值只是被忽略的字符串属性。
常见错误包括:
- 漏掉
extends参数:注册了customElements.define("my-btn", MyBtn),但 HTML 写<button is="my-btn"></button>→ 实例仍是HTMLButtonElement,不走MyBtn构造函数 - 注册名与
is值不一致:注册了"my-button",却写<button is="MyButton"></button>或<button is="mybutton"></button>→ 匹配失败,降级为原生按钮 - 继承类没正确扩展:类继承了
HTMLElement而非HTMLButtonElement,但又想用<button is="xxx"></button>→ 类型不匹配,浏览器拒绝升级
Vue 的 :is 和原生 is 机制完全不兼容
这是最容易混淆也最常出问题的地方。Vue 2 中的 <button is="my-component"></button> 是 Vue 模板编译器自己解析的语法糖,和 Web Components 规范无关;Vue 3 已移除该写法,只保留 <component :is=""></component> 形式。
而原生 is 是 HTML 标准的一部分,依赖浏览器原生 Customized Built-in Elements 支持。
两者混用(比如在 Vue 模板里直接写 <button is="my-btn"></button>)会导致:Vue 可能劫持该属性做组件替换,但 Web Components 注册未触发,结果 DOM 里既不是你写的 MyBtn 类实例,也不是预期的增强按钮,而是个行为残缺的普通按钮——表单提交失效、disabled 不同步、focus() 不响应、可访问性语义丢失。
实际使用时最关键的三个检查点
遇到 is 不生效,优先确认这三项:
- HTML 标签是否在可扩展列表中(查 WHATWG spec),不是所有标签都支持
-
customElements.define()是否带{ extends: "xxx" },且值与标签名严格一致(大小写、连字符、空格全部敏感) - 自定义类是否继承对应内置元素类(如
class MyButton extends HTMLButtonElement),且构造函数里调了super()
漏掉其中任一环,is 就只是个无意义的字符串属性。它不像 data- 那样宽松,而是个强契约机制——浏览器要么完整兑现,要么彻底忽略。











