我应该为移除的元素调用 ResizeObserver.unobserve 吗?

ami*_*mik 5 javascript resize-observer

当某些观察到的元素从 DOM 中删除时,我应该调用.unobserve该元素以防止内存泄漏,还是会“自动不被观察到”?

const ro = new ResizeObserver((entries) => { console.log(entries); });
const el = document.getElementById('foo');
ro.observe(el);
// ... some time later
el.remove();
ro.unobserve(el); // <-- is this needed, or does it happen automatically behind the scenes?
Run Code Online (Sandbox Code Playgroud)

为什么我问:我正在实现一个观察许多孩子的 React 组件,并正确清理未安装组件的观察者将涉及非平凡的代码,如果实际上不需要它,我想避免这种情况。

mcm*_*mik 15

根据csswg-drafts存储库中的问题,现在,如果您从 DOM 中删除该元素并从 JS 中删除任何引用,Chrome 会自动取消观察该元素。

let el = document.querySelector("#id");
let ro = new ResizeObserver();
ro.observe(el);
setTimeout(_ => {
  el.remove();
  el = null;
}
Run Code Online (Sandbox Code Playgroud)

如果没有 JS 引用,当前的 Chrome 代码会隐式取消观察元素。规范中没有捕获这一点。

但问题仍然悬而未决...


Dun*_*ain 9

是的,你应该使用unobserve()diconnect()。对于我自己的项目,当我不使用它时,我的应用程序中出现了内存泄漏。

我也发现使用很.unobserve()混乱。但如果提供了拆解......一般来说,使用它可能是一个很好的做法。在开发代码时添加绝对比在忘记为什么做某事后进行更新更容易。

我也在使用 React,但我使用 useEffect 钩子来清理它。

我必须进行一些尝试和错误才能找出有效的方法,并且最初也错过了.disconnect()对 ResizeObserver 的调用。

所以目前对我有用的是:

const [height, setHeight] = useState(null);
useEffect(() => {
  const heightObserver = new ResizeObserver((entries) => {
    setHeight(entries[0].contentRect['height']);
  });
  heightObserver.observe(el);

  return () => {
    if(el){
      heightObserver.unobserve(el);
    } else {
      heightObserver.disconnect();
    }
  }
},[]);
Run Code Online (Sandbox Code Playgroud)

在我的尝试和错误中,对我不起作用的是以下内容。

这将导致“el 不存在”错误:

...
  return () => {
    heightObserver.unobserve(el);
  }
...
Run Code Online (Sandbox Code Playgroud)

我可以对此进行测试,但这会导致内存泄漏:

...
  return () => {
    if(el){
      heightObserver.unobserve(el);
    }
  }
...
Run Code Online (Sandbox Code Playgroud)

然后我发现.disconnect(),虽然没有浏览器问题,但不幸的是,所需的行为仅通过以下方式停止运行:

...
  return () => {
    heightObserver.disconnect();
  }
...
Run Code Online (Sandbox Code Playgroud)

这就是我的过程,希望对某人有所帮助。我仍然觉得可能有更好的方法来做我正在做的事情,但据我所知,这是可行的。