is属性是定制化内置元素的唯一合法入口,必须用原生标签(如)配合is属性(如)并注册时指定{extends:"canvas"},才能使元素真正继承htmlcanvaselement原型链。

is属性是定制化内置元素的唯一合法入口
浏览器解析 HTML 时,不会根据 JavaScript 中的 customElements.define() 自动把任意标签名映射为扩展自某个内置类的实例。如果你写 <render-area></render-area> 并注册了 class RenderArea extends HTMLCanvasElement,这个元素在 DOM 中仍是 HTMLElement 实例,width、getContext() 等 canvas 特有属性和方法全部不可用——因为浏览器根本没把它当 canvas。
is 属性的作用就是显式告诉浏览器:“这个原生标签(比如 <canvas></canvas>)应该被我注册的自定义类接管”。只有这样,实例才真正继承 HTMLCanvasElement 的原型链和内置行为。
必须用原生标签 + is 属性,不能用自定义标签名
以下写法全部错误:
-
<render-area></render-area>—— 浏览器不认识该标签,降级为HTMLUnknownElement -
<canvas class="render-area"></canvas>—— class 不触发自定义类升级 -
<canvas is="render-area"></canvas>—— 正确,但前提是已用customElements.define("render-area", RenderArea, { extends: "canvas" })注册
关键点:
- 注册时必须传入
{ extends: "canvas" }(或"button"、"input"等),否则is无效 - HTML 中只能用
<canvas is="xxx"></canvas>,不能用<xxx></xxx> -
is值必须与customElements.define()第一个参数完全一致(大小写敏感)
data-* 和 is 属性毫无关系,别混用
有人误以为 data-is="xxx" 或 data-custom="canvas" 能替代 is,这是错的。HTML 规范中只有原生 is 属性具备语义升级能力;所有 data- 属性只是普通字符串数据,对元素类型、原型链、内置 API 完全无影响。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
常见混淆场景:
- 想用
<div data-role="canvas-wrapper"> 模拟 canvas 行为?不行,它没有 <code>getContext() - 用
element.setAttribute("is", "my-button")动态添加?无效,is只在元素创建时起作用(即 HTML 解析或document.createElement("button", { is: "my-button" })) - 服务端渲染时写死
<button is="my-button"></button>?可以,但需确保客户端已提前注册该类,否则降级为普通 button
动态创建定制化内置元素要用 createElement() 的第二个参数
不能靠 innerHTML = "<canvas is="render-area">"</canvas>,因为 innerHTML 解析不触发 is 升级。正确方式是:
const el = document.createElement("canvas", { is: "render-area" });
// 而不是:
// const el = document.createElement("render-area"); // ❌
// const el = document.createElement("canvas"); el.setAttribute("is", "render-area"); // ❌
注意:
- 必须用对象形式传参:
{ is: "xxx" },字符串形式(如"render-area")会报错 - 该 API 在 Safari 中支持较晚(iOS 16.4+/macOS 13.3+),旧版需降级处理或避免使用
- SSR 渲染后 hydrate 时,若 JS 尚未加载完成,
is元素会短暂表现为普通原生元素(如无宽高的<canvas></canvas>),这是预期行为
最易被忽略的一点:is 不是“加个属性就变类型”,它是声明式绑定,只在元素初始化阶段生效;后续修改 is 属性值不会改变实例类型,也不会重新构造原型链。










