Vue Intersect (Vue 2 Component)
Vue Intersect is a Vue 2 component designed to wrap the native Intersection Observer API, providing a declarative way to detect when an HTML element enters or leaves the viewport. Last published in March 2020 (version 1.1.6), this package is specifically compatible with Vue 2.x projects and has not been updated for Vue 3. Modern Vue 3 applications typically implement similar functionality using composables (e.g., `@intersection-observer/vue`) or directives, which align better with the Composition API. Due to its sole reliance on Vue 2 and lack of recent development, it is considered abandoned for new projects, though it remains functional for existing Vue 2 applications. Its primary differentiation was simplifying a browser API within the Vue 2 ecosystem.
Common errors
-
[Vue warn]: Unknown custom element: <Intersect> - did you register the component correctly?
cause The `Intersect` component has not been globally registered with `Vue.component` or locally imported and declared in the `components` option of the parent Vue component.fixGlobally register the component using `Vue.component('Intersect', VueIntersect);` or locally import it: `import Intersect from 'vue-intersect'; export default { components: { Intersect }, ... };` -
TypeError: Cannot read properties of undefined (reading 'isIntersecting')
cause This often occurs if the Intersection Observer callback receives an `entries` array that is empty or the `entry` object itself is undefined, usually when `v-if` conditionally renders the component, causing the observer to unobserve/reobserve unexpectedly or during initial setup.fixEnsure that you defensively check `if (entry && entry.isIntersecting !== undefined)` within your callback. For issues with `v-if`, ensure the observer instance is correctly managed or consider alternative patterns, as `vue-intersect` can have subtle interactions with conditional rendering.
Warnings
- breaking This package is built exclusively for Vue 2.x and is incompatible with Vue 3. Attempting to use it in a Vue 3 project will result in errors related to the Vue API.
- gotcha The Intersection Observer API is not supported in all browsers (e.g., Internet Explorer 11, older versions of Safari/iOS Safari). Without a polyfill, `vue-intersect` will not function in these environments.
- gotcha When observing elements, especially for `leave` events, ensure that the `threshold` prop includes `0`. If `0` is omitted from the `threshold` array (e.g., `[0.5, 1]`), the `leave` event may never fire as the observer won't trigger at the 0% intersection point.
Install
-
npm install vue-intersect -
yarn add vue-intersect -
pnpm add vue-intersect
Imports
- VueIntersect
const VueIntersect = require('vue-intersect');import Vue from 'vue'; import VueIntersect from 'vue-intersect'; Vue.use(VueIntersect);
- Intersect
import Intersect from 'vue-intersect';
- Intersect component usage
<template> <Intersect @enter="handleEnter" @leave="handleLeave"> <div>Content to observe</div> </Intersect> </template>
Quickstart
import Vue from 'vue';
import Intersect from 'vue-intersect';
Vue.component('Intersect', Intersect);
new Vue({
el: '#app',
data: {
isVisible: false
},
methods: {
handleIntersect(entry) {
this.isVisible = entry.isIntersecting;
console.log('Intersection changed:', entry.isIntersecting);
},
handleEnter(entry) {
console.log('Element entered viewport!', entry.target);
},
handleLeave(entry) {
console.log('Element left viewport!', entry.target);
}
},
template: `
<div id="app" style="height: 1200px; padding-top: 500px;">
<h1>Scroll down to see the intersection</h1>
<p>Visibility status: {{ isVisible ? 'Visible' : 'Hidden' }}</p>
<div style="height: 500px; background: #eee; margin-top: 200px;"></div>
<Intersect @change="handleIntersect" @enter="handleEnter" @leave="handleLeave" :threshold="[0, 0.5, 1]">
<div style="width: 300px; height: 200px; background-color: lightblue; border: 2px solid blue;">
This box is observed for intersection.
</div>
</Intersect>
<div style="height: 800px; background: #eee; margin-top: 200px;"></div>
</div>
`
});