最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Intersection Observer triggering callback twice on ngAfterViewInit - Stack Overflow

programmeradmin5浏览0评论

I tried to lazy load images using Intersection Observable in my angular 7 application. I called Intersection Observable from ngAfterViewInit lifecycle hook. But when i load the application, callback is called twice, once with all the isIntersecting values as true and the next one with the correct isIntersecting values. I am confused with this behaviour.

ngAfterViewInit() {
const imgOne = document.querySelectorAll('[data-class]');

    const options = {
      // root: document
      // threshold: 0
    };

    const observer = new IntersectionObserver((entries, observer) => {
      console.log(entries.length);
      entries.forEach((entry) => {
        // console.log(entry);
        if (!entry.isIntersecting) {
          return;
        } else {
          const el = entry.target;
          if (el.id === ('test' + this.testCount)) {
            console.log(entry);
          }
          // observer.unobserve(entry.target);
        }
      });
    });

    imgOne.forEach((eachQuery) => {
      observer.observe(eachQuery);
    });
 }

I tried to lazy load images using Intersection Observable in my angular 7 application. I called Intersection Observable from ngAfterViewInit lifecycle hook. But when i load the application, callback is called twice, once with all the isIntersecting values as true and the next one with the correct isIntersecting values. I am confused with this behaviour.

ngAfterViewInit() {
const imgOne = document.querySelectorAll('[data-class]');

    const options = {
      // root: document
      // threshold: 0
    };

    const observer = new IntersectionObserver((entries, observer) => {
      console.log(entries.length);
      entries.forEach((entry) => {
        // console.log(entry);
        if (!entry.isIntersecting) {
          return;
        } else {
          const el = entry.target;
          if (el.id === ('test' + this.testCount)) {
            console.log(entry);
          }
          // observer.unobserve(entry.target);
        }
      });
    });

    imgOne.forEach((eachQuery) => {
      observer.observe(eachQuery);
    });
 }

https://stackblitz./edit/angular-wqbuyr

UPDATE : Now intersection observer is called perfectly, but now a issue occured. Since we are using document.querySelectorAll which returns a static node list, once the array is updted node list is not updated. If i try to use document.getElementsByClassName, an error throws as it is not an Node list ???

Share Improve this question edited Sep 13, 2019 at 5:20 Ram asked Sep 10, 2019 at 15:29 RamRam 61111 silver badges21 bronze badges 8
  • Have you tried by this way observer.observe(imgOne);, no need foreach. – Shohel Commented Sep 10, 2019 at 16:59
  • Use the class into queryselector not the data attribute observer.observe(document.querySelectorAll('img.lzy_img')); – Shohel Commented Sep 10, 2019 at 17:02
  • It will thrown an error - 'Argument of type 'NodeListOf<Element>' is not assignable to parameter of type 'Element'.' as observe gets a single element as its argument not an array of elements. – Ram Commented Sep 10, 2019 at 18:48
  • Please create the example to stackblitz – Shohel Commented Sep 11, 2019 at 8:45
  • stackblitz./edit/angular-wqbuyr – Ram Commented Sep 12, 2019 at 7:35
 |  Show 3 more ments

2 Answers 2

Reset to default 5

Maybe this also works:

if (entry.isIntersecting && Math.floor(entry.intersectionRatio) === 1) { 
  const el = entry.target;
  if (el.id === ('test' + this.testCount)) {
    console.log(entry);
  }
} else {
  return;
}

"If you dont' check intersectionRatio ratio === 1, the observed element will trigger the callback twice, because when immediately passing/leaving 100% threshold, observer will trigger isIntersecting = true, intersectionRatio ~= 0.9 (maybe bug). Chrome somehow gets intersectionRatio slightly above 1 on the first box, so floor the value"

Source: https://codepen.io/mmanney/details/erpZbd

I solved the issue by removing ngOnInit(), as it was triggering ngAfterViewInit() again after loading.

发布评论

评论列表(0)

  1. 暂无评论