is属性仅对whatwg规范白名单中的约20个原生标签(如button、table、input等)生效,且必须同时满足三条件:customelements.define时指定extends、is值与定义名完全一致、自定义类继承对应内置元素并正确调用super()。

is属性只对特定原生标签生效,不是所有标签都能用
写 <div is="my-thing"> 或 <code><p is="highlight"></p> 完全无效——浏览器解析后仍是 HTMLDivElement 或 HTMLParagraphElement,自定义类根本不会被实例化。is 属性只在 WHATWG 规范白名单里的原生标签上起作用,比如:button、canvas、table、tr、td、p、input、video 等,共约 20 个。查不到列表?直接翻 WHATWG Customized Built-in Elements spec。
必须同时满足三个条件,is才真正生效
缺一不可,漏掉任意一个,is 就退化成普通字符串属性:
-
customElements.define("my-btn", MyButton, { extends: "button" })中的{ extends: "button" }不能省;没有它,<button is="my-btn"></button>仍是原生按钮 -
is属性值(如"my-btn")必须与define()第一个参数完全一致:大小写、连字符、拼写全部敏感 - 自定义类必须继承对应内置元素类,例如
class MyButton extends HTMLButtonElement,且constructor()首行必须调super()
常见错误:Vue 模板里混用 is 和 :is
Vue 2 的 <button is="my-component"></button> 是 Vue 自己解析的语法糖,和 Web Components 的 is 机制互不兼容;Vue 3 已移除该写法,只保留 <component :is=""></component>。两者混用后果严重:
- 在 Vue 模板中写
<button is="my-btn"></button>,Vue 可能劫持该属性做组件替换,但 Web Components 注册未触发 - 结果 DOM 中既不是
MyButton实例,也不是原生按钮:表单提交失效、disabled不同步、focus()报Illegal invocation、可访问性语义丢失 - 真实项目中,若需复用原生语义(如表单关联、键盘导航),优先用
is+extends;否则直接继承HTMLElement更稳妥,兼容性更好,行为更可控
is 属性不支持运行时修改,改了也没用
执行 el.setAttribute("is", "span-blue") 后,el.constructor 不变,el instanceof HTMLSpanElement 仍为 false,新增方法/属性访问一律 undefined。HTML 规范明确:is 只在元素创建时参与构造器选择,后续修改不触发原型重绑定。
想实现动态行为,得靠别的路子:
- 把逻辑从
constructor移到connectedCallback,用普通属性(如data-mode="blue")控制分支 - 真要“切换底层类型”,只能手动销毁旧节点、新建目标元素、迁移子节点——开销大,慎用
- 别在
attributeChangedCallback里监听is并试图调super(),它不会生效
customElements.define() 得放在 <button is="my-btn"></button> 所在 script 标签之前,或者确保在 DOMContentLoaded 前完成;否则即使代码都对,也会静默降级。











