自定义元素必须继承htmlelement或其子类,否则customelements.define()会报错;扩展现有元素需用is属性且值须完全一致;自治型表单控件需attachinternals()、formassociated:true、observedattributes及手动同步属性与状态。

自定义元素必须继承 HTMLElement 或其子类
不继承就根本注册不了,customElements.define() 会直接抛错:Failed to construct 'XXX': Please use the 'new' operator。哪怕你只想加个 click 日志,也得从 HTMLElement 出发——否则连 connectedCallback 这类生命周期钩子都收不到。
常见错误包括:
- 用对象字面量代替 class(
customElements.define('x-foo', { connectedCallback() {} })) - 用箭头函数或普通函数当构造器
- 继承了别的类(比如
EventTarget)而不是HTMLElement或HTMLInputElement等内置类
扩展现有元素必须用 is 属性,且值要完全一致
想让 <canvas></canvas> 带上自定义渲染逻辑?不能写 <render-area width="400"></render-area>,浏览器根本不认它是个 canvas,width、height、getContext() 全部返回 undefined。
正确写法只有一种:<canvas is="render-area" width="400" height="300"></canvas>。注意:
-
is的值必须和customElements.define()第一个参数**完全一致**(大小写、连字符都不能差) - 不能混用:既写
<render-area></render-area>又加is,浏览器会忽略你的类,当未知元素处理 -
extends: 'canvas'必须传给define(),且类必须继承HTMLCanvasElement
自治型表单控件必须手动接入表单生命周期
Chrome 100+ 已限制对 input、select 等内置表单元素的继承支持,现实路径只剩自治型方案——自己封装 DOM,再靠 attachInternals() 接入表单。
漏掉任意一步,form.elements 就拿不到它,提交时值也不会发出去:
- 构造函数里必须调用
this.attachInternals() - 注册时必须传
{ formAssociated: true },否则attachInternals()报错 -
connectedCallback中监听子input的事件,并调用this.internals.setFormValue() - 初始属性(如
value)需在attributeChangedCallback中同步到内部控件
属性监听不是自动的,observedAttributes 必须显式声明
attributeChangedCallback 不会响应 el.checked = true 这类 JS 属性赋值,只响应 HTML 属性变更或 setAttribute()。想做到双向同步,得自己补逻辑。
最容易踩的坑:
- 没写
static get observedAttributes()→ 回调压根不触发 - 把
checked当布尔值直接比较:oldValue === newValue→ 实际newValue是字符串或null - 初始 HTML 中的
<x-toggle checked></x-toggle>会触发一次回调,但oldValue是null,别直接拿来判断状态
最常被忽略的点是:自定义元素的语义和表单能力都不是“开箱即用”的,得手动设 role、aria- 属性,手动调 attachInternals(),手动映射属性——浏览器不会因为你写了 <date-picker></date-picker> 就自动理解它是日期选择器。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











