vue-intersection
Summary
vue-intersection
is a library that implements an IntersectionObserver
, which can be extremely helpful in a variety of scenarios. Probably the most common use case is for lazy loading images in a long gallery or for infinitely loading more content whenever the user scrolls to the bottom of your page, but it can be used to improve performance of scrollable UIs in any number of ways. You will find some other examples below. Whenever you want to offload an action until a particular element in scrolled into the user’s view, this is a great tool to help you do that with a very simple API.
Installation
yarn add vue-intersection
or
npm i --save vue-intersection
Basic Usage
Simply wrap your container in an IntersectionRoot
component and then wrap each child element that you want to observe in a IntersectionChild
component. The the Child
components do not have to be direct decendents of the Root
. You can have whatever content you need in between them. And not every child has to be observed. You can instead choose to observe only a few children if that is your use case. Then you can listen to whenever the child enters/leaves the container’s viewport by listening to the @enter
or @leave
events.
<template>
<IntersectionRoot :threshold="threshold" :rootMargin="rootMargin">
<IntersectionChild
v-for="child in children"
:key="child.id"
@enter="child.visible = true"
@leave="child.visible = false"
>
is visible
</IntersectionChild>
</IntersectionRoot>
</div>
</template>
<script>
import { IntersectionRoot, IntersectionChild } from 'vue-intersection'
export default {
name: "MyComponent",
components: { IntersectionRoot, IntersectionChild },
data() {
return {
threshold: 1,
rootMargin: "0px",
children: Array.from(Array(50).keys())
.map(id => ({ id, visible: false }))
};
};
}
}
</script>
API Details
IntersectionRoot
Prop | Type | Default | Description |
---|---|---|---|
threshold |
Array |
[0,1] |
Corresponds to the threshold option on the IntersectionObserver. Note: if you do not include 0 as a threshold value, the @leave event will never be fired. |
rootMargin |
Number /String |
"0px" |
Corresponds to the rootMargin option on the IntersectionObserver |
startThreshold |
Number /String |
"0px" |
Distance (px ) from the top of the container for when to fire the @start event |
endThreshold |
Number /String |
"0px" |
Distance (px ) from the bottom of the container for when to fire the @end event |
debounce |
Number |
10 |
Time (ms ) to debounce scroll events (only affects @start , @end , @middle , not @enter , @leave ). |
| Event | Type | Arguments | Optional |
| — | — | — | — |
| @start
| Function
| scroll
event | true
|
| @end
| Function
| scroll
event | true
|
| @middle
| Function
| scroll
event | true
|
NOTE: These 3 events are debounced and will fire (at most) once every 10ms, by default. If this is too frequent, set the debounce
prop to a higher delay, which will improve peformance. To capture all events, set debounce
to 0
.
IntersectionChild
Prop | Type | Default | Description |
---|---|---|---|
id |
String |
Randomly generated | If a IntersectionChild has an id property, it will be used as the unique identifier for scroll tracking. It is recommended to provide an id as it improves performance slightly. |
Event | Type | Arguments | Description |
---|---|---|---|
@enter |
Function |
IntersectionObserverEntry |
Will be fired whenever the child element enters the viewport of the IntersectionRoot container |
@leave |
Function |
IntersectionObserverEntry |
Will be fired whenever the child element leaves the viewport of the IntersectionRoot container |
Demo
You can find additional examples/demos below:
Browser Support
vue-intersection
works in all browsers that support the IntersectionObserver
API, which is essentially every major browser except for IE 11. If you need support for IE 11, you can use any of the IntersectionObserver
polyfills that are available. For a list of supported browsers, look here.
Alternative Libraries
heavyy/vue-intersect
arnellebalane/vue-intersect
vue-intersection-observer
- Vuetify’s
v-intersect
intersection-scroller-vue
Justification
- The main reason I added another library on top of these other options is because each of these above is creates a new
IntersectionObserver
instance for each element that is being observed. So if you’re trying to observe a large number of elements in a scrollable list, then that is a lot of observer instances. However,vue-intersection
was designed such that there is only one observer instance created for eachIntersectionRoot
component, which observes each of the nestedIntersectionChild
elements. Thus, the performance is much better for long lists of elements. - Another shortcoming that several of these other libraries have is that they don’t provide enough granular support on which container and which target elements to observe. Several of the above only support the root element being the
document.body
element, but often it is helpful to observe scrolling within some other element on your page.vue-intersection
allows for much more fine-grain control and flexibility while still maintaining a simple API.