Vue components are great, right? They encapsulate the view and behavior of your app into nice little composable pieces. If you need a little extra functionality on them, just attach directives! Thing is, directives are fairly inflexible and can’t do everything. Directives can’t (easily) emit events, for example. Well, this being Vue, of course there’s a solution. Abstract components!
Abstract components are like normal components, except they don’t render anything to the DOM. They just add extra behavior to existing ones. You might be familiar with abstract components from Vue’s built-in ones, such as <transition>
, <component>
, and <slot>
.
A great use-case for abstract components is tracking when an element enters the viewport with IntersectionObserver
. Let’s take a look at implementing a simple abstract component to handle that here.
If you’d like a proper production-ready implementation of this, take a look at vue-intersect, which this tutorial is based on.
First we’ll create a quick abstract component that simply renders its contents. To accomplish this, we’ll take a quick dip into render functions.
Congratulations! You now have an abstract component that, well, does nothing! It just renders its children.
Okay, now let’s stick in the logic for IntersectionObserver
.
IntersectionObserver
isn’t supported natively in IE or Safari, so you might want to go grab a polyfill for it.
Alright, so now we have an abstract component we can use like this:
We’re not done yet though…
We need to make sure not to leave any dangling IntersectionObservers
when the component is removed from the DOM, so let’s fix that real quick now.
And just for bonus points, let’s make the observer threshold configurable with props.
The final usage looks like this:
There you go! Your first abstract component.
Big thanks to Thomas Kjærgaard / Heavyy for the initial implementation and idea!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!