customelements.define() 是唯一入口,命名须含短横线,控制器类必须继承 htmlelement 并在 constructor 中调用 super()、attachshadow、读取初始属性;attributechangedcallback 仅响应 setattribute,需手动桥接 js 属性赋值;observedattributes 必须显式声明;shadow dom 内禁用内联事件,第三方库需绕过隔离;重复注册会报错,须加守卫判断。

customElements.define() 是唯一入口,不调用它,控制器类再完整也不会被 DOM 识别;命名必须含短横线(如 volume-controller),否则直接抛 DOMException: The element name must contain a hyphen。
controller 类必须继承 HTMLElement 并在 constructor 中调用 super()
漏掉 super() 会导致原型链断裂,this.getAttribute()、this.setAttribute() 全部失效,后续所有属性读写都不可靠。常见错误是把初始化逻辑全塞进 connectedCallback,结果首次插入时属性已丢失——因为 HTML 解析阶段的属性值只在 constructor 或 connectedCallback 初期可安全读取,而 constructor 是唯一能同步拿到初始属性的地方。
必须在 constructor 内完成三件事:
- 调用
super() - 调用
this.attachShadow({ mode: 'open' })(否则样式和结构无隔离) - 从
this.getAttribute('min')、this.getAttribute('max')等读取初始配置,存为实例属性(如this._min = Number(this.getAttribute('min')) || 0)
attributeChangedCallback 只响应 setAttribute 触发的变更
比如用户 JS 里写 el.value = 50,attributeChangedCallback 完全收不到;只有 el.setAttribute('value', '50') 或 HTML 中写 <volume-controller value="50"></volume-controller> 才触发。想让 JS 属性赋值也同步,得手动桥接:
- 在类中定义 getter/setter:
set value(v) { this.setAttribute('value', v); } - 在
attributeChangedCallback里解析字符串值:if (name === 'value') { const val = Number(newValue); this._input.value = val; this._updateUI(val); } -
static get observedAttributes()必须显式列出['min', 'max', 'value', 'step'],漏一个就监听不到
Shadow DOM 内部不能用内联事件,且第三方 UI 库需绕过隔离
写 <input type="range" oninput="this.parentNode.handleInput()> 在 Shadow DOM 中无效——内联事件作用域不进入 shadowRoot。必须用 this.shadowRoot.querySelector('input').addEventListener('input', ...) 绑定。
如果控制器依赖外部 UI 库(如 noUiSlider),Shadow DOM 会阻断其样式注入和 DOM 查询。此时有两个选择:
- 放弃 Shadow DOM,改用 light DOM + 命名空间 class(如
.volume-controller__slider),靠 CSS 作用域控制样式泄露 - 保留 Shadow DOM,但把渲染容器设为 light DOM 节点:
<volume-controller><div slot=" target>,然后在connectedCallback里把第三方实例挂到this.querySelector('[slot="target"]')最易被忽略的是:同一个名字注册两次会硬性报错,且无法覆盖。上线前务必加守卫
if (!customElements.get('volume-controller')) { customElements.define('volume-controller', VolumeController); }—— 否则热更新或多次加载脚本时,控制台直接卡死。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











