用 is 属性扩展原生元素必须满足三要素:正确注册、严格匹配、原生标签限定,缺一即退化为 htmlunknownelement 且无报错;仅约20个原生标签支持 is,需配合 extends 选项注册,is 值须与定义名完全一致,super() 必须在 constructor 首行调用,is 不可运行时修改,ssr 或 innerhtml 中写 is 无效。

用 is 属性扩展原生元素,不是“加个属性就增强”,而是必须满足三要素:正确注册、严格匹配、原生标签限定。漏掉任一条件,元素就安静地变成 HTMLUnknownElement,所有内置能力(width、getContext()、value)全失效,且浏览器不报错。
为什么 <canvas is="my-renderer"></canvas> 能用,而 <my-renderer></my-renderer> 不行
浏览器解析 HTML 时只认标准标签名。<my-renderer></my-renderer> 无论是否注册过类,都会生成 HTMLUnknownElement 实例——它没有 width 属性,调 getContext() 报错,表单也不收集它。is 是唯一能让浏览器把 <canvas></canvas> “升级”为你的定制类的入口,本质是告诉解析器:“这个原生标签该走我定义的逻辑”。
-
is必须配合原生标签使用:仅<button></button>、<input>、<canvas></canvas>、<table>、<code><tr>、<code><p></p>等约 20 个标签支持,<div> 或 <code><span></span>加is会被静默忽略 -
customElements.define("my-renderer", MyRenderer, { extends: "canvas" })中的{ extends: "canvas" }不可省略,漏掉则is完全不触发升级 -
is值(如"my-renderer")必须与define()第一个参数完全一致:大小写、连字符、空格都敏感 -
this.width始终为0,哪怕 HTML 里写了width="400" -
this.value读不到初始值,但getAttribute("value")还能取到字符串 -
connectedCallback里补super()没用,必须在构造函数首行 -
el.constructor.name不变,仍是原来的类名 -
el instanceof HTMLButtonElement结果不变 - 所有新定义的方法、属性访问都报
undefined
constructor 里不写 super() 会怎样
直接报错:Failed to construct 'HTMLButtonElement': Please use the 'new' operator。这不是警告,是 WebIDL 层强制校验——super() 负责绑定底层 DOM 对象状态,比如初始化 this.width、关联表单、设置默认 disabled 状态。漏掉或延迟调用会导致:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
is 属性能不能运行时修改来切换行为
不能。HTML 规范白纸黑字写明:is 只在元素创建时起作用。执行 el.setAttribute("is", "other-button") 后:
真要实现“切换”,得靠普通属性驱动逻辑分支(比如监听 mode),或者手动销毁重建——后者代价高,且需迁移子节点、事件监听器、焦点状态等细节,容易出错。
服务端渲染或 innerHTML 里写 is 有用吗
没用。SSR 或 innerHTML = "<canvas is='\"my-renderer\"'>"</canvas> 时,JS 尚未执行 customElements.define(),DOM 中生成的就是普通原生元素;hydrate 时也不会自动“补救”。必须确保注册早于元素挂载,否则 is 属性只是个无意义字符串。
最容易被忽略的一点:你写的 is 值哪怕只差一个连字符或大小写,或者注册时漏了 { extends: "canvas" },整个机制就彻底失效,而且浏览器不报错、不警告,只会安静地当它是个普通未知元素处理。










