attributechangedcallback 是唯一标准、可依赖的属性观察机制,它仅响应 dom attribute 变更,要求 observedattributes 显式声明小写连字符格式的属性名,且 oldvalue 和 newvalue 恒为字符串。

attributeChangedCallback 是唯一标准、可依赖的属性观察机制,其他方式(比如监听 setAttribute、用 MutationObserver 监听整个元素)要么不可靠,要么无法复用、不响应生命周期。
observedAttributes 必须显式声明
浏览器只对出现在 observedAttributes 静态 getter 返回数组里的属性名做变更响应。没列进去的,哪怕你写了 data-id="123",attributeChangedCallback 也完全不会触发。
- 属性名必须是小写连字符格式(kebab-case),比如
"data-config"、"max-length",不能写成"dataConfig"或"maxLength" -
observedAttributes是静态 getter,不是普通数组:static get observedAttributes() { return ["disabled", "value", "data-theme"]; } - 布尔属性如
disabled、loading也要列进去,否则初始化时的 HTML 属性不会触发回调
attributeChangedCallback 只响应 attribute 变更
这个回调只在 DOM attribute 被修改时执行,和 JS 属性(property)无关。常见错误是把 el.value = "new" 当作 attribute 变更——它不会触发回调,也不会更新 HTML 中的 value 属性。
- 触发场景只有三种:
el.setAttribute("value", "x")、el.removeAttribute("value")、HTML 初始化(如<my-input value="init"></my-input>) -
oldValue和newValue永远是字符串,哪怕你设的是数字或布尔值:el.setAttribute("count", 42)→newValue === "42" - 想判断布尔属性是否存在,用
this.hasAttribute("disabled"),别用this.getAttribute("disabled") === "true"
data-* 属性需要手动声明和解析
data-* 属性不会自动被观察,必须显式加入 observedAttributes,且值始终是字符串,需自行解析。
- 例如要响应
data-config='{"theme":"dark"}',得先写"data-config"到observedAttributes - 在
attributeChangedCallback里用JSON.parse(newValue),但必须加try/catch,因为用户可能填错 JSON 格式 - 不要直接改
this.dataset.config——这不会触发回调,也不影响getAttribute("data-config")的返回值 - 数字类
data-count建议用Number(newValue) || 0,避免parseInt("", 10)返回NaN
定制内置元素(extends)的属性识别陷阱
如果你扩展的是 HTMLCanvasElement 这类内置元素,直接用 <my-canvas width="500"></my-canvas> 是无效的——浏览器当它是 autonomous element,width 不会映射到实例的 .width 属性上。
- 必须用原生标签 +
is属性:<canvas is="my-canvas" width="500"></canvas> - 此时
width和height才能被正确反射为 JS 属性,并在connectedCallback中读取 -
observedAttributes依然只管 attribute 变更,JS 属性赋值(如el.width = 600)不会触发attributeChangedCallback
容易被忽略的一点:attribute 变更和 JS 属性是两套系统,attributeChangedCallback 从不关心后者,也从不自动同步两者。你得自己决定是否要在回调里同步更新 JS 属性,或者反过来,在 setter 里调用 setAttribute。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











