Intersection Observer API: Callback function is not triggered on intersection

Viewed 118

There is a Vue custom directive for lazy loading

 export default {
    mounted: el => {
      function loadImage() {
        console.log("loadImage called!")
        el.src = el.dataset.src
      }

      //loadImage();
  
      function handleIntersect(entries, observer) {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            loadImage();
            console.log("loadImage called! from handleIntersect")
            observer.unobserve(el);
          }
        });
      }

      function createObserver() {
        const options = {
          root: null,
          threshold: 0
        };  
        const observer = new IntersectionObserver(handleIntersect, options);
        observer.observe(el);
      }

      if (window["IntersectionObserver"]) {
        createObserver();
      } else {
        loadImage();
      }
    }
  };

Which is registered in Vue 3 component locally

<template>
    <figure>
      <img :data-src="src" @load="imageLoaded = true" v-show="imageLoaded">
     <Skeletor height="160" v-if="!imageLoaded"/>
    </figure>
    
</template>
<script>
import lazyload  from "../../../directives/lazyload"
export default {
  
  ...
  directives: {
    lazyload
  },
  data() {
    return {
      imageLoaded: false
    }
  }

}
</script>

The callback function handleIntersect is not triggered on Intersection and the images always have the data-src with the image url when I inspect them in the DevTools

However, when I uncomment calling of loadImage() function in the directive, first it is called by each elements (144 altogether) and then I see that loadImage() is called by the callback function handleIntersect as the images enter the viewport.

The example below has 3 images in the viewport

enter image description here

What is wrong with the code? Why callback function is called on Intersection once loadImages is fired for all elements and not fired at all when it is commented (console shows no output of "loadImage called!")?

Appreciate any support!

1 Answers

The reason for event not being fired was that the img was zero width/heigh or just simply put non-existent (DevTools showed style='display: none;') for Intersection Observer. When I uncommented loadImage() in the custom directive, it became visible and event was fired.

The solution was to move v-lazyload to figure and search by img tag for the target element in the custome directive, so that figure always hosts a skeletor (component from vue-skeletor package)

Related