Dylan Tientcheu I build experiences to make your everyday life simpler.

Supercharge your Vue.js and Nuxt.js apps with VueUse

7 min read 2034

Vue.js and Nuxt.js are frameworks already well known for their awesome developer experience. Since Vue 3 was released (on which Nuxt 3 is written), we are provided with set of APIs that allow us to author Vue components using imported functions instead of declaring options. This is commonly known as the composition API. This API enables us to create abstractions on Vue’s Reactivity API, Lifecycle Hooks and its underlying dependency injection system.

In this article, we shall discuss how Vue developers can leverage VueUse’s functions to efficiently simplify development and reduce boilerplate code, while allowing them to quickly prototype and test ideas.

Contents

VueUse and the composition API

VueUse coins itself as a collection of essential Vue composition utilities. VueUse leverages its power from the API offered by the composition API, and provides more than 200 flexible and typesafe functions that add basic interactions in your components that may otherwise require code from you.

The VueUse playground enables you to experiment with the APIs as much as you want. This playground is just the perfect addition to such an extensive library. We have the ability to install other libraries, play with VueUse’s functions in real time, and even share the link to the playground on which you are experimenting.

Any developer could indeed write a composable function that looks like the ones offered by VueUse, however, VueUse functions are structured, tested, and optimized, making it a functional Swiss Army Knife for any Vue developer.

Getting started with VueUse

Because VueUse is just a collection of functions, getting started with it should be as seamless as adding a utils file in your project and simply importing functions from it.

To install VueUse in your Vue project, you can either get it via npm install:

npm i @vueuse/core

Or through the CDN, exposing it as window.VueUse:

<script src="https://unpkg.com/@vueuse/shared"></script>
<script src="https://unpkg.com/@vueuse/core"></script>

Check out their getting started page for installing on Nuxt and other environments.

Composing with VueUse

Using composables with VueUse is easy. You are given a function that does exactly one utility, or provides a set of features. This function handles the whole complexity behind the feature, and is able to return refs, which are reactive and mutable objects in Vue. The ref is then used as a Vue reactive variable and can be used or mutated

We made a custom demo for .
No really. Click here to check it out.

Below is an example of the useClipboard VueUse function. This composable function is able to read and write from the clipboard, as well as respond to copy, cut, and paste commands. and even check if it is supported in the current environment:

import { useClipboard } from '@vueuse/core'

const source = ref('Something you need to copy')
const { text, copy, copied, isSupported } = useClipboard({ source })

The usage is easy and very flexible; you are able to use it all around your Vue app. The function will return the refs of the variables that you need. The useClipboard source code is concise yet complete, offering you the simplest API needed to implement this functionality.

In case you want to use the same functions with reactive rather than refs, you can simply wrap them with vue’s reactive() function:

import { reactive } from 'vue'
import { useMouse } from '@vueuse/core'

const clipboard = reactive(useClipboard())

// "all available refs" will be unwrapped.
console.log(clipboard.copied)

Configuring composables

VueUse functions provide a lot of flexibility, for example, you have the ability to throttle, debounce or even pause them using Event Filters:

import { debounceFilter, throttleFilter, useMouse } from '@vueuse/core'

// mouse position will be updated after mouse idle for 1s
const { x, y } = useMouse({ eventFilter: throttleFilter(1000) })

// mouse position will be updated after mouse idle for 100ms
const { x, y } = useMouse({ eventFilter: debounceFilter(100) })

VueUse also enables further configuration on reactive timing for other specific functions. You have the ability to change when the events happen relative to Vue lifecycle events.

Renderless components

VueUse provides renderless components via the @vueuse/components package. In renderless components, ref binding is done automatically and VueUse provides ready-to-use components with slots and props to catch events and trigger and edit components.

Below is an example of a VueUse component that enables us to “eye drop” (catch colors) in a webpage:

<script setup>
import { useEyeDropper } from '@vueuse/components'
<script/>

<template>
  <UseEyeDropper v-slot="{ isSupported, sRGBHex, open }">
    <button :disabled="!isSupported" @click="open">
      sRGBHex: {{ sRGBHex }}
    </button>
  </UseEyeDropper>
<template>

The same function could also provide usable reactive refs if imported from @vueuse/core. This gives developers the best available flexibility to use and reuse these functions.

VueUse’s library of functions is completely tree-shakable, tested, typed, SSR-friendly and well optimized for Vue, making it safe and developer friendly.

Using composables concisely with Reactivity Transform

Reactivity Transform is an experimental compile-time transform that allows us to access our Vue ref without using .value. They are created by prefixing $ on the equivalent macro, like so:

  • ref$ref
  • computed$computed
  • shallowRef$shallowRef
  • customRef$customRef
  • toRef$toRef

For VueUse, this means that we are able to use the refs resulting from the composable in a destructured way:

import { useMouse } from '@vueuse/core'
const { x, y } = $(useMouse())
console.log(x, y) // no need to write x.value and y.value 

Standout functions in VueUse

We can obviously build a lot of cool things with the functions coming from VueUse; each function has a specific use case. Below, you can find an outline on how we can use some of these functions to easily build and extend mind-blowing interfaces and interactions.

On VueUse, functions are separated by category and regrouped into two different types: core and add-ons. Core functions are lightweight and dependency free functions which internally use Vue reactivity to perform a task. Add-ons are wrapped functional versions of popular packages following the composable fashion.

In the following sections, I will list each category with a brief explanation of the functions it contains and examples of what you can build with them.

Browser

Browser functions are reactive functions will the ability to interact with the browser API. You have the ability to check permissions; use APIs like notifications, fullscreen, and vibration; and even manipulate your UI based on breakpoints (useBreakpoint).

Sensors

Sensor functions are able to capture user events and use the device API. These functions range from grabbing different events from the mouse or keyboard (useMousePressed, useMouse, onStartTyping, onMagicKeys) to DOM emitted events like useElementHover and onClickOutside.

VueUse sensor functions are great due to their relation with reactivity. Sometimes you need the events in real time, but sometimes you may need to throttle them, which VueUse accomplishes well.

Animation

Animation functions are mostly time-related. They are not only specific to animations, however; you can also use them to update your UI based on time.

These functions include useNow and useTimestamp, giving us the current date (in real time). We also have useInterval and useTimeout, which act like JavaScript setTimeout and setInterval, and useTransition. which can perform very simple to complex and custom transitions.

VueUse also exposes an add-on called @vueuse/motion. @vueuse/motion uses popmotion under the hood to enables you to create beautiful animations. @vueuse/motion also allows you to use its API as a directive or as a composable. Visit the docs for more examples on how to animate with this great add-on.

State

State functions enable you to access everything related to your Vue components and browser states. The highlights in this category are createGlobalState, useLocalStorage and useRefHistory.

createGlobalState can be used to create a reusable and shareable state amongst different Vue instances. useLocalStorage enables us to use the browser’s localStorage reactively, and useRefHistory tracks the change history of a ref.

Elements

Element components help you reactively access the state of your HTML elements. You can use useMouseInElement to get the relative position of the mouse in an element, or useDraggable to make any HTML element draggable. The useDraggable function is extremely powerful, because you are able to track them position-wise and persist their coordinates in the browser storage.

Component

Component functions allow you to handle many aspects of your components reactively. There are functions to bind template refs in order to safely interact with the components lifecycle.

My highlight in this category is useVirtualList, which is able to virtualize a rendered array into one line. This function allows you to render the minimum number of elements necessary to show the items from an array within a container.

Watch

Watch functions act like the Vue watch feature on steroids. They give you the ability to watch only once, watch and filter events, watch in a debounced or throttled way, and even watch and ignore certain changes.

Network

These are functions that interact with network events. They are able to make async HTTP calls and return the state of the call or connection.

The highlighted function in this category is useFetch and useWebSocket, because they could probably be another package on their own and still be very popular.

useFetch enables us to fetch, refetch, intercept, and abort HTTP requests in our Vue app. It is very powerful because of the way it handles reactivity; the function returns refs and callbacks that enable you to track the state of the request, abort, and fire other functions after fetch events.

VueUse also provides a composable wrapper around the Axios library. useAxios implements all of the Axios features while keeping Vue’s reactivity on the events.

Utilities

This category contains any other function that may help you create or handle reactive elements and functions in your Vue app.

The functions discussed above are just an overview of some of the 200+ functions available to you, and the list keeps getting bigger.

Apps you can build with VueUse

  • Complex and animated drag and drop interfaces like the Trello kanban board could easily be implemented using the @vueuse/gesture add-on package
  • An image classification UI enabling users to select a part of an image and classify could be built by combining useDraggable and useResizeObserver to help the user create selection boxes and track their position relative to the image being classified
  • VueUse could be a good companion while creating games on the browser thanks to its support for input with @vueuse/gestures, useGamepad, useMagicKeys, and useMouse. This simplifies the code written to interact with the native APIs

The VueUse contributors always look for creative ways to show examples of how to leverage each function. Going through the docs can be a source of inspiration to developers.

Writing your own composable

Writing Vue composables is as easy as using them. Below is an example of a composable that helps reactively track the position of the mouse:

// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'

// by convention, composable function names start with "use"
export function useMouseCustom() {
  // state encapsulated and managed by the composable
  const x = ref(0)
  const y = ref(0)

  // a composable can update its managed state over time.
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }

  // a composable can also hook into its owner component's
  // lifecycle to setup and teardown side effects.
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))

  // expose managed state as return value
  return { x, y }
}

The useMouseCustom function above follows some of the outlined guidelines exposed by VueUse. These guidelines help you write better composables, which are backwards compatible between Vue versions and have minimal or no side effects.

Conclusion

I believe VueUse is a great addition to Vue’s ecosystem. The value it brings in terms of developer experience is enormous. The library is approachable by developers of any level and open to any possible improvement.

In this post, we’ve seen how VueUse leverages the power of the composition API to create functions that can supercharge your development workflow. These functions are tested, safe and easy to integrate on your Vue/Nuxt apps of any size.

Experience your Vue apps exactly how a user does

Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Vue apps - .

Dylan Tientcheu I build experiences to make your everyday life simpler.

Leave a Reply