customelements.define() 无法可靠继承 htmlinputelement 等内置表单元素,因现代浏览器已策略性移除该能力;唯一稳定方案是自治型自定义元素 + attachinternals()。

customElements.define() 不能用来可靠继承 HTMLInputElement 等内置表单元素——这不是写法不对,是现代浏览器(Chrome 100+、Firefox、Safari)已策略性移除该能力。
为什么 extends="input" 在 Chrome 里会静默失效
你写了 class MyInput extends HTMLInputElement,又调用 customElements.define('my-input', MyInput, { extends: 'input' }),看似合法,但实际运行时:
- Chrome 100+ 会直接抛出
NotSupportedError或静默降级为普通HTMLElement - 即使构造函数中调用了
super(),插入 DOM 后也缺失原生input的关键行为:比如focus()不触发光标、selectionStart读不到、input事件触发时机错乱 -
<input is="my-input">写法在 IE 完全不可用;React/Vue/Svelte 对is属性支持极弱,需手动 patch 或绕过框架渲染 - 表单提交时,该元素不会出现在
FormData中,form.reset()对它完全无效
attachInternals() 是唯一稳定接入表单管线的路径
自治型自定义元素(继承 HTMLElement)+ attachInternals(),才是当前唯一能落地的方案:
-
this.internals = this.attachInternals()必须在constructor中调用,且只能一次 -
this.internals.setFormValue(value)替代直接赋值this.value,否则FormData拿不到值 -
this.internals.setValidity({ valid: false }, '错误信息')才能触发:invalid伪类和原生校验 UI(如红边框) - 必须显式监听内部
<input>的input或change事件,并调用setFormValue,否则表单值永远为空
继承 HTMLCanvasElement 这类非表单元素要注意 is 属性写法
如果你扩展的是 HTMLCanvasElement、HTMLButtonElement 等非表单控件,extends 仍可能工作,但实例化方式极易出错:
- 错误写法:
<my-canvas width="300" height="200"></my-canvas>→ 浏览器当它是HTMLElement,width和height属性不生效(返回undefined) - 正确写法:
<canvas is="my-canvas" width="300" height="200"></canvas>→ 此时才真正继承HTMLCanvasElement接口,属性可读可写 - 所有主流框架对
is属性支持差,Vue/React 渲染时会丢掉is,需用ref+ 原生 DOM 操作补救
别指望 HTML 属性或 CSS 样式“自动继承”到自定义元素内部
自定义元素本身不继承父级的 class、data-*、disabled 等 HTML 属性,CSS 也只按标准继承规则走:
-
color、font-family这类可继承 CSS 属性会向下传;margin、padding、background等不可继承,子元素必须显式设置 - 表单控件(包括你封装的
<my-input></my-input>)默认忽略父级文字样式,需加font-family: inherit才能接住 - 想让自定义元素响应
disabled,得自己监听attributeChangedCallback并同步内部控件状态,浏览器不会自动代理
valueAsNumber、checkValidity()、reportValidity() 这些 API,只有通过 attachInternals() 显式桥接才能用,靠继承根本拿不到。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











