JSFiddle - React, Tailwind, and code Playground

Vue + intersection observers, parent has observer and passes data down to component through a prop

by Travis Almand

HTML

<div id="app">
  <section-a class="full-height" data-example="example-1" :entry="entries['example-1']"></section-a>
  <section-a class="half-height" data-example="example-2" :entry="entries['example-2']"></section-a>
  <section-a class="full-height" data-example="example-3" :entry="entries['example-3']"></section-a>
  <section-a class="half-height" data-example="example-4" :entry="entries['example-4']"></section-a>
  <section-a class="full-height" data-example="example-5" :entry="entries['example-5']"></section-a>
</div>

CSS

.full-height {
  background-color: #E0E0E0;
  border: 1px solid black;
  min-height: 100vh;
  transition: 0.5s;
}
.half-height {
  background-color: #E0E0E0;
  border: 1px solid black;
  min-height: 50vh;
  transition: 0.5s;
}
.sticky {
  left: 0;
  padding: 10px;
  position: sticky;
  top: 0;
}
.isIntersecting {
  background-color: #663399;
  color: #fff;
}

JavaScript

console.clear();

Vue.component('section-a', {
  template: `
  	<div :class="{isIntersecting: entry.isIntersecting}">
    	<div class="sticky">{{ entry.isIntersecting }} {{ entry.intersectionRatio }}</div>
    </div>`,
  props: {
    entry: {
    	type: Object,
      default: () => {
      	return {
        	isIntersecting: Boolean,
          intersectionRatio: Number
        }
      }
    }
  }
});

new Vue({
  el: "#app",
  data () {
  	return {
    	io_options: {
        root: null,
        rootMargin: '0px',
        threshold: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
      },
    	observer: null,
      entries: {}
    }
  },
  
  methods: {
  	io_callback: function (entries, observer) {
      entries.forEach(entry => {
        this.$set(this.entries, entry.target.dataset.example, {isIntersecting: entry.isIntersecting, intersectionRatio: entry.intersectionRatio});
      });
    }
  },
  
  mounted () {
  	this.observer = new IntersectionObserver(this.io_callback, this.io_options);
    
  	document.querySelectorAll('[data-example]').forEach(example => {
    	this.observer.observe(example);
    });
  }
})