自定义元素应在disconnectedcallback中主动清理资源。该回调是唯一可靠时机,需清除定时器、事件监听器及observer等,确保函数引用一致且调用对应销毁方法。

自定义元素(Custom Element)在被移除时,若不主动清理定时器、事件监听器等资源,极易引发内存泄漏或逻辑错乱。关键不是“等它被删”,而是“在它被删前完成收尾”。
用 connectedCallback 和 disconnectedCallback 做生命周期钩子
浏览器原生支持自定义元素的两个核心生命周期回调:connectedCallback(挂载时触发)和 disconnectedCallback(从 DOM 中移除时触发)。后者是清理操作的**唯一可靠时机**。
-
disconnectedCallback会在元素被remove()、innerHTML = ''、replaceChild等任何方式断开 DOM 树时调用,且此时元素仍可安全访问其属性、子节点和绑定状态 - 不要依赖
attributeChangedCallback或手动监听父节点变化——它们无法覆盖所有移除路径 - 注意:该回调不保证元素一定还在文档中,但能确保它尚未被垃圾回收,适合做同步清理
清理定时器必须保留 ID 并显式清除
所有通过 setTimeout、setInterval、requestAnimationFrame 启动的异步任务,都需在 disconnectedCallback 中终止。
- 把定时器 ID 存在实例属性上(如
this._timerId = setTimeout(...)),避免闭包捕获导致无法访问 - 在
disconnectedCallback中检查并清除:this._timerId && clearTimeout(this._timerId) - 对
setInterval要格外小心——漏清会导致持续执行,即使界面已不可见
事件监听器必须用同一函数引用添加和移除
不能在 connectedCallback 里用匿名函数绑定,在 disconnectedCallback 里又写一遍匿名函数试图移除——这完全无效。
- 把处理函数定义为类方法或实例属性上的箭头函数(如
this._onClick = (e) => {...}),并在两个回调中复用 - 绑定目标要明确:绑定在自身(
this.addEventListener)的,就在disconnectedCallback中解绑;绑定在window或document的,也必须在此处解绑,否则永久驻留 - 使用
addEventListener的once: true选项仅适用于一次性事件,不适用于需主动控制生命周期的场景
连带清理 Observer 和第三方 SDK 实例
自定义元素常集成 MutationObserver、ResizeObserver 或图表/地图 SDK,这些对象不会随元素移除自动销毁。
- 创建后存为实例属性(如
this._resizeObserver = new ResizeObserver(...)) - 在
disconnectedCallback中调用.disconnect(),并置为null防止重复调用 - 查阅所用 SDK 文档,调用其明确提供的销毁方法(如
chart.dispose()、map.remove()),不要假设它会自动释放











