Vue 3 introduced several new concepts and different ways of handling logic, one of which is Vue composables. Vue composables allow us to extract reactive state and functionality to reuse in other components.
In this article, we‘ll gain a comprehensive understanding of Vue composables by implementing them in a Vue application. Let’s get started!
Vue composables are functions that use the composition API to implement a reactive and reusable logic. Composables act as an external function that extracts reactive state and functionality to be used across several other components. Composables can alternatively be called composition functions.
Composables are similar to mixins in the Options API In Vue 2, as well as the implementation of Hooks in React.
In modern web applications, the codebase is always divided into different components, providing an organized structure and easy workflow. With composable functions, you can further simplify your workflow by extracting and importing functionality into an external file that can then be used in multiple components.
The concept behind composable functions is brought about by the Composition API, which gives you the full flexibility to organize your component code into smaller functions based on logical concerns.
The reusable features of a composable function offer many benefits. For one, the extracted logic can be reused, promoting code organization with a structure that is easy to navigate. Composables can also serve as a utility function that uses a reactive state and can be customized for different purposes in an application.
Finally, composables can manage the state of the output depending on the use case, allowing you to choose whether the state should be global or local. This freedom eliminates some of the complexity and dependencies in comparison to other state management tools.
Another interesting thing about composables is that they can be nested within each other, meaning one composable function can call one or more other composable functions. Therefore, we are able to break down complex logic into smaller units, like how we separate an entire application using components.
Let’s try it out by creating and using composables in a Vue application. To follow along with this tutorial, you’ll need Node.js and the Vue CLI installed. First, create the Vue project as follows:
vue create vue-composables
Once the project has been created, navigate into vue-composables
with the following code:
cd vue-composables
For an organized structure, we’ll create a separate folder to handle all the composables needed for the project.
Using the Web Speech API, we’ll create a custom composable that is used for speech recognition. The Web Speech API enables developers to implement speech recognition and speech synthesis features in the web browser, giving web apps the ability to convert voice data into readable text formats. In this tutorial, we’ll create a speech recognition composable that will be reusable in your apps.
The API is initialized with the SpeechRecognition()
constructor, which creates a new speech recognition object instance.
There are some important things to take note of when creating a composable, including naming conventions. Composable functions use camel casing, where the name starts with the prefix use
. For example, our composable function for the demo would be named useSpeechRecognition
.
Just like a regular function, a composable accepts parameters that can be used for functions that require dynamic data. It is best to return a refs
object from composables. Therefore, the values will still retain their reactivity even when the composable is destructured for use in different components.
The basic structure of every composable is as follows:
export default function useComposableFunction() { // The logic return {// return values} }
Let’s create the useSpeechRecognition
composition function. In the composable
folder, create a new file called useSpeechRecognition.js
, then place the following logic functionality inside it:
import { ref,watch} from 'vue' // the function accepts parameters export function useSpeechRecognition({lang,continuous,interimResults}) { const isListening = ref(false) const isFinal = ref(false) const result = ref('') const error = ref(') // Intialize the web speech API const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition // Checks if the browser supports the API const isSupported = Boolean(SpeechRecognition) // The speech recognition constructor const recognition = SpeechRecognition? new SpeechRecognition() : false // a function to set it for listening const start = () => { isListening.value = true } // a function to stop it from listening const stop = () => { isListening.value = false } // Checks if the browser supports if (isSupported) { recognition.continuous = continuous recognition.interimResults = interimResults recognition.lang = lang recognition.onstart = () => { isFinal.value = false } // the method to get the result of the transcription recognition.onresult = (event) => { // raw words that the user spoke const transcript = Array.from(event.results) .map((result) => { isFinal.value = result.isFinal return result[0] }) .map(result => result.transcript) .join('') result.value = transcript error.value = undefined } // method to handle error recognition.onerror = (event) => { error.value = 'Speech recognition error detected: ' + event.error } recognition.onend = () => { isListening.value = false } watch(isListening, () => { if (isListening.value) // Starting the speech recognition recognition.start() else // stopping the recognition recognition.stop() }) } }
Using the Web Speech API, we were able to create a function to accept voice sounds from a user and convert them into readable text. First, we ensured that our function accepts parameters, then initialized the Web Speech API, checking that is is supported by the browser. We added a function to check that our API is listening with isListening.value
, setting the value to either true
or false
.
With the recognition.onresult
method, we get the result of the transcription. Additionally, we added some error handling methods. This format saves us the stress of having to replicate this logic in different files depending on what we are building.
Next, we return the values and methods in an object:
return { isSupported, isListening, isFinal, recognition, result, error, start, stop, }
Then, we use the composable in a component. In the App.vue
file, we first import the following function:
import {useSpeechRecognition} from './composables/useSpeechRecognition'
By calling the function, we store the returned values from the composable. We also pass the parameter values:
const { isListening, isSupported, stop, result,start,error } = useSpeechRecognition({ lang:'en-US', continuous: true, interimResults : true, })
With this set up, we then return the values from the composable that will be used in the component:
return {isListening,isSupported,stop,result,start,error}
Finally, we implement the function in our component:
<template> <div class="app"> <div v-if="!isSupported"> Your browser does not support SpeechRecognition API, <a href="https://caniuse.com/mdn-api_speechrecognition" target="_blank" >more details</a> </div> <div v-else > <header> <h1> Speech Recognition </h1> <i class="header-icon fas fa-microphone-alt"></i> </header> <main> <div class="mic-buttons"> <!-- To handle the controls --> <button v-if="!isListening" @click="start"> Speak </button> <button v-if="isListening" class="orange" @click="stop"> Stop </button> </div> <h2> English Transcript </h2> <!-- Conditionals to handle errors --> <p v-if="error" >{{error}}</p> <div v-else> <textarea v-model="result" class="text-transcript" cols="30" rows="10"> </textarea> </div> </main> </div> </div> </template>
Here’s the link to the complete code, in case you want to try it out.
With this composable, we are easily able to implement a speech recognition feature in our Vue apps that is also reusable for different functionalities.
An alternate approach for using composables in your Vue application is through external open source libraries, which are created to leverage custom composition API functions.
Written fully in TypeScript, the VueUse library provides over 200 composable functions that work for both Vue 2 and 3 apps. The functions can be customized and used in your projects via the CDN or installed directly with npm:
npm i @vueuse/core <script src="https://unpkg.com/@vueuse/core"></script>
The documentation is well written with interactive demos and code. The functions are categorized into nine types: Browser, Sensors, Animation, State, Elements, Component, Watch, Network, Utilities, and Misc. You can get more information about the different functions from the official documentation.
vue-composable is a library that provides ready-to-use, generic composition API functions. vue-composable is built fully with TypeScript and supports both Vue 2 and Vue 3 apps. You can install it using either Yarn or npm:
# install with yarn yarn add @vue/composition-api vue-composable # install with npm npm install @vue/composition-api vue-composable
Some of the categories of functions that it provides are Events, Dates, Format, Breakpoint, Storage, i18n, and Web. You can learn more from the official documentation.
Composable functions extract the logic functionality separately to be reused across several other components, saving you the stress of having to replicate your code in multiple different instances to achieve the same result.
The concept behind composables changes the way we handle reusability in our applications, offering a simpler, flexible, and more efficient approach. Now is a good time to refactor your codebase to use composables in your applications!
If you have any questions, you can definitely reach out to me on Twitter or leave a comment below. Thanks for reading!
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 manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.