当 dom 中不再存在元素时,SetInterval 继续在 webcomponent 中运行
Posted
技术标签:
【中文标题】当 dom 中不再存在元素时,SetInterval 继续在 webcomponent 中运行【英文标题】:SetInterval keeps running in webcomponent when element is not present in dom anymore 【发布时间】:2022-01-20 10:29:28 【问题描述】:目前,我正在开发一个可以编排多个 Web 组件的简单应用程序。其中一个组件包含一个 setInterval 函数。即使组件本身不再存在于 dom 中,该函数也会继续运行。谁能给我解释一下为什么会这样?
这是一个简单的复制:
const selectorEl = document.getElementsByTagName('body')[0];
selectorEl.innerhtml = '<my-component></my-component>'; // Append custom component to body
class WebComponent extends HTMLElement
constructor()
super();
this.innerHTML = '<span>This should not be visible since I am removed instantly!</span>';
setInterval(() => console.log('I am still running...'), 2000);
window.customElements.define('my-component', WebComponent);
selectorEl.innerHTML = ''; // Remove element from the dom directly
【问题讨论】:
setInterval
将一直运行,直到您调用 clearInterval
,它与 DOM 无关。
“即使组件本身不再存在于 dom 中,该功能也会继续运行。有人可以向我解释为什么会这样吗?” - 因为有这两件事之间绝对没有关系......?!?从现在开始,您指示浏览器每隔一段时间执行一个函数。 DOM 与这...有什么关系?
谢谢,基思。你知道如果它们没有清理这个逻辑,是否可以强制停止 web 组件内的所有运行间隔?
您可能希望使用生命周期回调,developer.mozilla.org/en-US/docs/Web/Web_Components/…
@Tom 如果您不使用泄漏计时器控制 Web 组件,您可以 proxy 窗口计时器(timeout 和 interval)以维护您自己的计时器 ID 列表和根据您自己的标准清除它们。
【参考方案1】:
您需要使用lifecycle callbacks才能正确使用setInterval
和clearInterval
。
示例如下:
const selectorEl = document.getElementsByTagName("body")[0];
selectorEl.innerHTML = "<my-component></my-component>"; // Append custom component to body
class WebComponent extends HTMLElement
connectedCallback()
this.innerHTML =
"<span>This should not be visible since I am removed instantly!</span>";
this.interval = setInterval(
() => console.log("I am still running...", Math.random()),
2000
);
disconnectedCallback()
clearInterval(this.interval);
window.customElements.define("my-component", WebComponent);
setTimeout(() => selectorEl.innerHTML = "",7000); // Remove element from the dom directly
【讨论】:
警告!此代码在document.createElement("my-component");
上失败,因为constructor
不应添加DOM 元素,该工作应在connectedCallback
中完成。只有当您在 conctructor
中创建 shadowRoot 时,您才能添加 HTML(到 shadowDOM)
@Danny'365CSI'Engelman,非常感谢您对这个问题的关注。我错过了这一点并在代码中更正了它:)【参考方案2】:
您需要使用 disconnectedCallback 钩子,一旦组件从 dom 中删除,它将被调用,因此在此函数中,您可以清除间隔。
disconnectedCallback()
clearInterval(interval)
【讨论】:
【参考方案3】:Web 组件有自己的生命周期,当从 DOM 中删除元素时,disconnectedCallback()
会被调用。当元素从 DOM 中移除时调用 is 生命周期钩子。因此,它是添加清理逻辑和释放资源的理想场所。在您的情况下,请调用 clearInterval
方法,该方法会像您一样清除使用 setInterval() 方法设置的计时器。
disconnectedCallback()
clearInterval(interval)
【讨论】:
【参考方案4】:一个更简洁的例子:
<script>
customElements.define("my-component", class extends HTMLElement
connectedCallback()
console.log("connectedCallback" , this.isConnected);
this.innerHTML = "A Web Component";
setTimeout(() => this.remove(), 2000); // triggers disconnectedCallback
this.interval = setInterval(() => this.innerHTML += ".", 50);
disconnectedCallback()
console.log("disconnectedCallback" , this.isConnected);
clearInterval(this.interval);
);
</script>
<my-component></my-component>
注意事项
disconnectedCallback
中不再存在 DOM 元素,但 Web 组件仍然存在于内存中,因此您可以访问之前创建(或附加)的任何内容
拖放或append
操作触发disconnectedVCallback
然后再次触发connectedCallback
【讨论】:
以上是关于当 dom 中不再存在元素时,SetInterval 继续在 webcomponent 中运行的主要内容,如果未能解决你的问题,请参考以下文章
Capybara/Cucumber In Ruby:当不再存在元素时停止搜索
Internet Explorer:当目标 DOM 元素在 DOM 中移动时,悬停状态变为粘滞状态