Web Components 的 attributeChangedCallback 仅在继承 HTMLElement、声明 observedAttributes 且通过 DOM API 修改属性时触发,newValue/oldValue 恒为字符串,初始属性需在 connectedCallback 中手动读取。

Web Components 通过 attributeChangedCallback 实现属性变化监听,但必须满足几个硬性条件,否则改了属性也不会触发回调。
必须继承 HTMLElement 并声明观察的属性名
自定义元素类要继承 HTMLElement,并在静态 getter observedAttributes 中明确列出你想监听的属性(全小写、带连字符):
-
✅ 正确写法:
static get observedAttributes() { return ['disabled', 'data-id', 'max-count']; } -
❌ 错误写法:漏写该 getter;或写成驼峰名如
'maxCount';或大小写不一致如'Disabled'
只响应 DOM API 触发的属性变更
这个回调不会捕获所有“看起来像修改属性”的操作,仅对以下方式生效:
el.setAttribute('data-id', '123')el.removeAttribute('disabled')- 直接修改 HTML 字符串(如
el.innerHTML = '<my-input data-id="456"></my-input>') -
不生效的操作:
el.dataId = '789'、el.disabled = true、初始 HTML 中写的<my-comp data-id="init">(首次渲染不进回调)
回调内处理要注意类型和副作用
attributeChangedCallback(attrName, oldValue, newValue) 的三个参数中,newValue 和 oldValue 永远是字符串,且可能为 null(比如首次设置时):
- 数值需手动转换:
const count = Number(newValue) || 0 - 布尔值别依赖真假判断:
if (newValue === 'true'),而不是if (newValue) - 避免在回调里反复调用
setAttribute同一属性,否则会无限循环 - 不要在里面做重操作(如请求、重绘),它可能高频触发
初始属性值要靠 connectedCallback 补读
HTML 中直接写的属性(如 <my-button disabled>)不会触发 attributeChangedCallback。你需要在 connectedCallback 里主动读取:
this.disabled = this.hasAttribute('disabled');this.id = this.getAttribute('data-id') || '';- 再根据这些值初始化内部状态、样式或无障碍属性


















