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.
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.
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.
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
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)
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.
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.
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
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 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
).
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 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 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
.
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 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 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.
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.
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.
@vueuse/gesture
add-on packageuseDraggable
and useResizeObserver
to help the user create selection boxes and track their position relative to the image being classified@vueuse/gestures
, useGamepad
, useMagicKeys
, and useMouse
. This simplifies the code written to interact with the native APIsThe 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 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.
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.
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.
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 — start monitoring for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.