自定义元素生命周期钩子是强制接口:constructor仅初始化,不可操作DOM;connectedCallback是发起请求和初始化UI的唯一可靠时机;attributeChangedCallback需声明observedAttributes才生效;disconnectedCallback必须清理资源防内存泄漏。
HTML 自定义元素(Custom Elements)的生命周期钩子不是“可选增强”,而是资源管理的强制接口——漏掉
很可能造成内存泄漏,而过早在
里操作 DOM 会直接报错。
constructor 中只能做基础初始化,不能访问 this.shadowRoot 或 document
这是最容易踩的坑:自定义元素类的
在元素被创建但尚未插入 DOM 时就执行,此时
为
,
也查不到自己。
✅ 正确做法:只声明属性、绑定方法、创建私有变量(如
)
❌ 错误写法:
或
⚠️ 注意:不能在
中调用
之后再写异步逻辑(如
),因为此时元素仍处于未挂载状态,DOM 不可用
connectedCallback 是发起请求和初始化 UI 的唯一可靠时机
触发表示元素已插入文档,此时
可用,且能安全调用
、
、
等。
✅ 推荐模式:在
中检查是否已初始化(用布尔标志位),避免重复挂载时重复请求或重复绑定
✅ 若需响应属性变化,应在
中显式调用一次
同步初始值
⚠️ 注意:该钩子可能被多次触发(如元素被移出又重新插入),所以所有副作用必须可重入
attributeChangedCallback 必须显式声明 observedAttributes 才生效
即使你写了
方法,如果没在类上定义静态 getter
,浏览器根本不会调用它。
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
立即学习
“
前端免费学习笔记(深入)
”;
✅ 正确写法:
✅ 参数顺序固定:
,其中
和
均为字符串,需手动转换类型(如
或
)
⚠️ 注意:首次设置属性(如
)时,
为
,不是
;后续变更才走正常对比
disconnectedCallback 是清理定时器、事件监听和 MutationObserver 的最后机会
这个钩子常被忽略,但它是防止内存泄漏的关键防线。一旦元素从 DOM 移除,但还持有对全局对象的引用(比如
、
、
),就会导致节点无法被 GC 回收。
✅ 必须清理:
、
、
✅ 推荐加 guard:
⚠️ 注意:
不保证一定会执行(比如页面刷新、iframe 卸载),所以关键资源释放逻辑不应只依赖它;但组件内可控制的部分(如本组件创建的定时器、观察者)必须在这里清理
真正难的不是记住这四个钩子的名字,而是判断哪段逻辑该放在哪个钩子里——尤其是当组件支持 SSR 或跨 shadow boundary 渲染时,
的触发时机可能比预期晚,而
又不处理初始属性。这时候,一个带状态缓存的初始化守卫比硬编码更可靠。
disconnectedCallbackconstructorconstructorthis.shadowRootnulldocument.querySelectorthis._timer = nullthis.shadowRoot.innerHTML = '...' this.querySelector('input')constructorsuper()setTimeoutconnectedCallbackthis.shadowRootfetchaddEventListenerrequestAnimationFrameconnectedCallbackconnectedCallbackthis.attributeChangedCallbackattributeChangedCallbackobservedAttributesstatic get observedAttributes() { return ['label', 'disabled', 'value']; }attributeChangedCallback(attrName, oldValue, newValue)oldValuenewValueJSON.parseNumber()oldValuenullundefinedsetIntervalwindow.addEventListenernew MutationObserverclearInterval(this._timer)removeEventListenerobserver.disconnect()if (this._timer) { clearInterval(this._timer); this._timer = null; }disconnectedCallbackconnectedCallbackattributeChangedCallback