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

Should I call ResizeObserver.unobserve for removed elements?

当某些观察到的元素从 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?

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

根据 csswg-drafts 存储库中的 issue,如果您从 DOM 中删除该元素,今天 Chrome 会自动取消观察该元素并删除 JS 中的所有引用。

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

Current Chrome code implicitly unobserves element if there are no JS references to it. This is not captured by the specification.

但问题仍然存在...

是的,您应该使用 unobserve()diconnect()。对于我自己的项目,当我不使用它时,我的应用程序会发生内存泄漏。

我还发现 .unobserve() 的使用令人困惑。但是,如果提供了拆解……一般来说,使用它可能是一种很好的做法。在您开发代码段时添加绝对比在您忘记为什么做某事后在将来更新更容易。

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

我必须反复试验才能找出有效的方法,并且最初还错过了对 ResizeObserver 的 .disconnect() 调用。

所以目前对我有用的是:

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();
    }
  }
},[]);

在我的反复试验中,以下内容对我不起作用。

这会导致 'el does not exist' 错误:

...
  return () => {
    heightObserver.unobserve(el);
  }
...

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

...
  return () => {
    if(el){
      heightObserver.unobserve(el);
    }
  }
...

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

...
  return () => {
    heightObserver.disconnect();
  }
...

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