【问题标题】:IntersectionObserver callback firing immediately on page load页面加载时立即触发 IntersectionObserver 回调
【发布时间】:2018-11-08 18:36:33
【问题描述】:

我对@9​​87654321@ 很陌生,我一直在试验这段代码:

let target = document.querySelector('.lazy-load');

let options = {
    root: null,
    rootMargin: '0px',
    threshold: 0
}

let observer = new IntersectionObserver(callback, options);

observer.observe(target);

function callback() {
    console.log('observer triggered.');
}

这似乎可以正常工作,并且每当.lazy-load 元素进入视口时都会调用callback(),但callback() 也会在页面初始加载时触发一次,这会触发`console.log('observer触发.');

页面加载时是否有理由触发此回调?还是我的实现方式有误?

编辑:将代码更改为以下代码仍会在页面加载时触发回调。

let target = document.querySelector('.lazy-load');

let options = {
    root: null,
    rootMargin: '0px',
    threshold: 0
}

let callback = function(entries, observer) {
    entries.forEach(entry => {

        console.log('observer triggered.');

    });
};

let observer = new IntersectionObserver(callback, options);

observer.observe(target);

【问题讨论】:

  • 我有类似的问题,但阈值为 1.. 所以这里的答案不适用

标签: javascript lazy-loading intersection-observer


【解决方案1】:

这是默认行为。当您实例化 IntersectionObserver 的实例时,callback 将被触发。

建议提防这种情况。

entries.forEach(entry => {
  if (entry.intersectionRatio > 0) {
    entry.target.classList.add('in-viewport');
  } else {
    entry.target.classList.remove('in-viewport');
  }
});

我还发现这篇文章和文档非常有帮助,特别是关于 IntersectionObserverEntry 上的 intersectionRatioisIntersecting 属性。

·https://www.smashingmagazine.com/2018/01/deferring-lazy-loading-intersection-observer-api/

·https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver

·https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry

【讨论】:

  • 很棒的答案。谢谢。
  • 我认为依赖isIntersecting 会更好,因为有时我会看到intersectingRatio 为零但isIntersecting 为真的情况——在我的情况下这是正确的行为。
  • @zenw0lf 好点!这就是我在这里所做的……github.com/snewcomer/intersection-observer-admin/blob/…
  • 遗憾的是,当它不与 .unobserve() 元素相交时,您不能使用这种情况。只有一些丑陋的突变器标记元素是否已经在视口中
  • '当你实例化 IntersectionObserver 的实例时,回调将被触发'。我的理解是,第一次调用新的 IntersectionObserver 的观察方法时,它会调用回调。如果您有一个按钮来调用观察方法,那么它应该异步调用 IntersectionObserver。
【解决方案2】:

听起来很简单,我可以通过

解决问题
  1. 添加阈值比较条件
  2. 为观察者的初始化添加轻微延迟
    const options = {
      threshold: 1.0,
    };

      setTimeout(() => {
        observer = new IntersectionObserver(([entry]) => {
          console.log("OBSERVER TRIGGERED 1");

          if (
            entry &&
            entry.isIntersecting &&
            entry.intersectionRatio >= options.threshold
          ) {
            console.log("OBSERVER TRIGGERED 2");
          }
        }, options);

        observer.observe(observerRef.value);
      }, 2000);

我还建议临时将可观察元素的背景颜色更改为:

.observer {
  background-color: red;
}

并进行页面刷新。这样,您可能会真正看到屏幕上闪烁的红色背景,从而触发事件。

现在,在你向我扔西红柿之前 - 就我而言 - 我的网页上有十几个视频。视频 HTML 元素不会立即“扩展”,因为浏览器需要下载有关海报图像的信息。因此页面已加载,但视频仍在加载。添加轻微延迟解决了问题,因此浏览器有时间扩展视频内容。

【讨论】:

    猜你喜欢
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多