constructor 不能访问 dom 或属性,因为元素尚未插入文档,此时 this.innerhtml 为空、getattribute() 返回 null、shadowroot 未创建;connectedcallback 才是初始化 shadow dom、读取属性、绑定事件、调用 attachshadow 和 attachinternals 的唯一可靠时机。

constructor 里只能做最基础的初始化,不能操作 DOM、读取属性、设置样式,否则会失败或被忽略。
为什么 constructor 不能访问 DOM 或属性?
浏览器在解析 HTML 时,遇到自定义标签(如 <my-input></my-input>)会立即调用其 constructor,此时元素尚未插入文档,this.innerHTML 为空,this.getAttribute() 返回 null(即使 HTML 中写了 value="abc"),shadowRoot 也未创建。强行操作会导致报错或静默失效。
connectedCallback 是真正的“启动入口”
只有当元素真正挂载到 DOM 后,connectedCallback 才会被触发——这是你初始化 Shadow DOM、读取初始属性、绑定事件、设置默认值的唯一可靠时机。
- 必须在这里调用
this.attachShadow({ mode: 'open' }),否则样式和结构无法隔离 - 要用
this.getAttribute('value')或this.hasAttribute('value')拿初始值,再同步到内部<input> - 若需表单集成,
formAssociated: true已在类定义中声明,但this.attachInternals()必须在此回调里执行 - 监听内部
<input>的input事件,并调用this.internals_.setFormValue()同步值
attributeChangedCallback 不会响应初始属性值
哪怕你在 HTML 中写了 <my-input value="test"></my-input>,attributeChangedCallback 也不会在首次渲染时触发——它只对后续的 JS 修改(如 el.setAttribute('value', 'new'))生效。
- 必须在
connectedCallback中手动读取并应用初始属性 - 若要响应变化,需显式声明
static observedAttributes = ['value', 'disabled'] - 注意:布尔属性(如
disabled)在 HTML 中存在即为true,但getAttribute('disabled')返回空字符串而非"true",建议用this.hasAttribute('disabled')
别在 constructor 里设 tabIndex 或监听 focusin
label 点击聚焦失效、屏幕阅读器卡住,八成是因为这个坑:在 constructor 里提前给根节点加 tabIndex="0",或试图监听 focusin,此时元素还没挂载,事件根本不会绑定成功。
- 所有事件监听(包括
focusin、click)必须放在connectedCallback中 - 聚焦代理逻辑(如点击 label 后 focus 内部
<input>)也要在此处 setup - 若依赖
this.internals_,确保它已在connectedCallback中通过this.attachInternals()获取
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











