IntersectionObserver unobserve 不在回调中处理目标?

IntersectionObserver unobserve not working on target in callback?

我正在尝试在用户向下滚动时向页面添加元素。当最后一个元素完全出现时,我希望调用观察者回调,创建一个新元素,观察者设置为观察新元素并不再观察当前目标。

function observerCallback(entries, observer) {
  entries.forEach((entry) => {
    const newDiv = document.createElement('div')
    observer.observe(newDiv)
    document.body.appendChild(newDiv)
    observer.unobserve(entry.target);
  });
}

然而,这并没有像我预期的那样工作,回调一直被调用并且新元素被生成。我已经设置了一个 codepen 来演示这个问题。

为什么会这样?

这只是您在职能中做事的顺序吗?由于某些原因,CodePen 在我的 iPad 上不起作用,所以我现在无法测试它。

function observerCallback(entries, observer) {
  entries.forEach((entry) => {
    const newDiv = document.createElement('div')
    observer.unobserve(entry.target)
    document.body.appendChild(newDiv)
    observer.observe(newDiv)
  });
}

您必须检查 entry 是否可见(与容器相交)

if (entry.isIntersecting) {
   //...
}

然后才(或者如果阈值高于某个值)向 DOM 添加一个新元素。

let observer = new IntersectionObserver(observerCallback, { threshold: 1.0 });

function observerCallback(entries, observer) {
  entries.forEach((entry) => {
    if (!entry.isIntersecting) {
      return;
    }

    const newDiv = document.createElement('div')
    observer.observe(newDiv)
    document.body.appendChild(newDiv)
    observer.unobserve(entry.target);
  });
}

observer.observe(document.querySelector('div'))
div { height: 50px; background-color: red; margin-bottom: 20px }
<div></div>

只是调用 IntersectionObserver.observe(target) 会触发 target 的回调。

const observer = new IntersectionObserver(entries => {
  console.log( 'new entry!', entries[0].target );
});
// wait a bit to show that it's really the call to observe() that does trigger the callback
setTimeout(()=> {
  // even if not attached
  const elem = document.createElement('div');
  observer.observe( elem );
}, 2000);

所以unobserve工作正常,只是新观察到的元素本身会触发新的回调调用。

不知道你到底想做什么,所以很难告诉你如何修复你的代码,但这应该可以帮助你找到正确的路线,也许你只是在寻找 isIntersecting 属性,因此当最后一个元素不再可见时它会停止。

let observer = new IntersectionObserver(observerCallback, { threshold: 1.0 });

function observerCallback(entries, observer) {
  entries.forEach((entry) => {
    if( !entry.isIntersecting ) {
      return;
    }
    const newDiv = document.createElement('div')
    observer.observe(newDiv)    
    document.body.appendChild(newDiv)
    observer.unobserve(entry.target);
  });
}

observer.observe(document.querySelector('div'))
div {
  height: 20px;
  background-color: red;
  margin-bottom: 5px;
}
<div></div>