fbpx

5 VueUse Library Functions That Can Speed Up Development

VueUse is an open-source project by Anthony Fu that provides Vue developers with a huge collection of essential Composition API utility functions for both Vue 2 and Vue 3. 

It has dozens of solutions for common developer use cases like tracking ref changes, detecting element visibility, simplifying common Vue patterns, keyboard/mouse inputs, and more. It’s a great way to really save time in development because you don’t have to add all of this standard functionality on your own. 

I love the VueUse library because it really puts the developers first when deciding what utilities to provide, and it is a well-maintained library as it stays up to date with the current versions of Vue. 

What kind of utilities does VueUse have?

If you want to see the complete list of every single utility, I definitely recommend checking out the official documentation. But to summarize, there are 9 types of functions in VueUse. 

  1. Animation – contains easy to use functions for transitions, timeouts, and timing
  2. Browser – can be used for different screen controls, clipboard, preferences, and more
  3. Component – provides a shorthand for different component methods
  4. Formatters – provides reactive time formatting functions
  5. Sensors – used to listen to different DOM events, input events, and network events
  6. State – manage a user state (global, local storage, session storage)
  7. Utility – different utility functions like getters, conditionals, ref synchronization, and more
  8. Watch – more advanced types of watchers like pausable watchers, debounced watchers, and conditional watchers
  9. Misc. – different types of functionality for events, WebSockets, and web workers 

Most of these categories contain several different functions so VueUse is flexible for your use case and can serve as an excellent place to start building Vue apps quickly. 

In this tutorial, we’ll be taking a look at 5 different VueUse functions so you can get an idea of how easy it is to work inside this library. 

But first, let’s add it to our Vue project!

Installing VueUse into your Vue Project

One of the best features of VueUse is that it is compatible with both Vue 2 and Vue 3 from just one package! 

There are two options for installing VueUse: npm or CDN

npm i @vueuse/core # yarn add @vueuse/core
<script src="https://unpkg.com/@vueuse/shared"></script>
<script src="https://unpkg.com/@vueuse/core"></script>

I recommend using the NPM as it makes the usage much easier to understand, but if we using the CDN, VueUse will be accessible in the app via window.VueUse

For NPM installs, all the functions can be accessed by importing them from @vueuse/core using standard object destructuring like this:

import { useRefHistory } from '@vueuse/core'

Alright – now that we have VueUse installed, let’s use it inside of our app!

useRefHistory to track changes to reactive data

useRefHistory tracks every change made to a ref and stores it inside of an array. This allows us to easily provide undo and redo functionality to our application. 

Let’s look at an example where we’re building a text area that we want to be able to undo. 

The first step is creating our basic component without VueUse – using a ref, textarea, and buttons for undo and redo. 

[gist]https://gist.github.com/matthewmaribojoc/604abb597e04dd267acff26941178fd5[/gist]

Then, let’s add VueUse by importing the useRefHistory function and then extracting the history, undo, and redo properties from our text ref. This is as simple as calling useRefHistory and passing our ref. 

import { ref } from 'vue'
import { useRefHistory } from '@vueuse/core'

const text = ref('')
const { history, undo, redo } = useRefHistory(text)

This triggers a watcher every time our ref changes – updating the history property that we just created. 

Then, so we can really see what’s going on, let’s print out history inside of our template and also call our undo and redo functions whenever the corresponding button is clicked. 

[gist]https://gist.github.com/matthewmaribojoc/a1d7b197e452ed11cc4e646b65027a04[/gist]

Okay – let’s run it. As we type, every character triggers a new entry in our history array, and if we click undo/redo, we’ll go to the corresponding entry.

There are also different options that add even more functionality to this function. For example, we can track reactive objects deeply and limit the number of history entries like this.

const { history, undo, redo } = useRefHistory(text, {
  deep: true,
  capacity: 10,
})

For a full list of options, be sure to check out the documentation. 

onClickOutside to close modals

onClickOutside detects any click made outside of an element. In my experience, the most common use case for this feature is closing any modal or popup window. 

Typically, we want our modal to block out the rest of the webpage to draw a user’s attention and limit errors. However, if they do click outside of the modal, we want it to close.

There are just two steps to do this:

  1. Create a template ref for our element that we want to detect
  2. Run onClickOutside using this template ref 

Here’s a simple component with a popup window using onClickOutside

[gist]https://gist.github.com/matthewmaribojoc/d63589ce3c85be7dbd9e71f512c35c7d[/gist]

The result is like this, where we can open the popup with our button, and then close it by clicking outside the popup-content window. 

Clicking inside the content doesn’t do anything, but clicking outside does!

useVModel simplifies v-model binding

A common use case for Vue developers is creating a custom v-model binding for a component. This means that our component accepts a value as a prop, and whenever that value is modified, our component will emit an update event to the parent. 

For a full tutorial on building custom v-models, check out our complete guide on the topic.

The useVModel function simplifies this into just using the standard ref syntax. Let’s say that we have a custom text input that is trying to create a v-model for the value of its text input. Typically, we would have to accept a prop for the value, and then emit a change event to update the data value in the parent component.

Instead of using ref and calling props.value and update:value, we can use useVModel and treat it just like a normal ref! This helps reduce the number of different syntaxes that we need to remember!

[gist]https://gist.github.com/matthewmaribojoc/a02bd6bf325b7f961b68ea07bb99b856[/gist]

Whenever we need to access our value, we just call .value and useVModel will give us the value from our component props. And whenever we change the value of our object, useVModel will emit an update event to the parent component. 

Here’s a quick example of what that parent component might look like…

[gist]https://gist.github.com/matthewmaribojoc/5cdf3a7f9bd3a0a62c58ed5d7317e3ac[/gist]

The result looks something like this, where our value in our parent always stays up to date with the input in the child.

useIntersectionObserver to track element visibility

Intersection Observers are very powerful when determining whether or not two elements are overlapping. A great use case for this is when checking if an element is currently visible in the viewport. 

Essentially, it checks what percentage of a target element is intersecting with a root element/document. If that percentage crosses a certain threshold, it invokes a callback determining whether or not the target element is visible or not.

useIntersectionObserver provides an easy syntax to use the IntersectionObserver API. All we need to do is provide a template ref for the element we want to check. By default, IntersectionObserver will use the document’s viewport as the root with a threshold of 0.1 – so when that threshold is crossed in either direction, our intersection observer will trigger. 

The code for that example might look something like this where we have a dummy paragraph that just takes up space in our viewport, our target element, and then a print statement printing the visibility of our element…

[gist]https://gist.github.com/matthewmaribojoc/0c58749470dc7304b76bc54db2f423c6[/gist]

And when we run it and scroll, we’ll see that it updates properly.

We can also specify more options for our Intersection Observer like changing its root element, margin (offsets to the root’s bounding box for calculating intersections), and threshold levels. 

const { stop } = useIntersectionObserver(
      target,
      ([{ isIntersecting }], observerElement) => {
        targetIsVisible.value = isIntersecting
      },
      {
        // root, rootMargin, threshold, window
        // full options in the source: https://github.com/vueuse/vueuse/blob/main/packages/core/useIntersectionObserver/index.ts
        threshold: 0.5,
      }
)

It’s also important to see that this method returns a stop function that we can call to stop observing the intersection. This is especially useful if we only want to track the first time an element is visible on the screen.

In this code snippet, once targetIsVisible is set to true, the observer will stop and our value will stay true even after we scroll away from our target element.

const { stop } = useIntersectionObserver(
      target,
      ([{ isIntersecting }], observerElement) => {
        targetIsVisible.value = isIntersecting
        if (isIntersecting) {
          stop()
        }
      },
    )

useTransition to ease between values

useTransition is one of my favorite functions in the entire VueUse library. It allows us to smoothly ease between numerical values in just one line. 

We have a numerical source stored as a ref and an output that will be the one that eases between different values. For example, let’s say we want to build a counter like the one on the sign-up page for our Vue 3 cheatsheet.

We can do that in three steps:

  • Creating our count ref and initializing it to zero
  • Creating our output ref with useTransition (setting our duration and transition type)
  • Changing the value of count 
<script setup>
import { ref } from 'vue'
import { useTransition, TransitionPresets } from '@vueuse/core'

const source = ref(0)

const output = useTransition(source, {
  duration: 3000,
  transition: TransitionPresets.easeOutExpo,
})

source.value = 5000

</script>

Then, inside our template, we want to display the value of output because that is the one that will smoothly transition between the different values. 

[gist]https://gist.github.com/matthewmaribojoc/ba4a8793c96a7193cd81644e5f7a14bf[/gist]

And here’s the result!

We can also use useTransition to transition an entire array of numbers. This is useful when working with positions or colors. A great trick for working with colors is to use a computed property to format the RGB values into the correct color syntax.

[gist]https://gist.github.com/matthewmaribojoc/8afd16ff18897bd9698a0bbd2f2a5245[/gist]

Some cool ways to customize this even further is using any of the built-in Transition Presets or defining our own using a CSS easing function. 

Final Thoughts

This is by no means a complete guide to VueUse. These are just many of the functions that I find the most interesting to get introduced to the VueUse library. 

I love how helpful all of these utility functions are in speeding up development because each of them was designed to solve specific, yet common use cases. 

I’d love to hear how you’re implementing VueUse in your own projects. Leave any comments down below.
Happy coding!