JAVASCRIPT
Vue 3 Composable for Debounced Input Handling
Optimize performance and prevent excessive function calls by implementing a reusable debounce composable in Vue 3 for input fields and other rapid events.
// composables/useDebounce.js
import { ref, watch, onUnmounted } from 'vue'
/**
* A composable to debounce a value.
* @param {import('vue').Ref} valueRef The ref to watch for changes.
* @param {number} delay The debounce delay in milliseconds.
* @returns {import('vue').Ref} A ref with the debounced value.
*/
export function useDebounce(valueRef, delay = 500) {
const debouncedValue = ref(valueRef.value)
let timeoutId = null
watch(valueRef, (newValue) => {
if (timeoutId) {
clearTimeout(timeoutId)
}
timeoutId = setTimeout(() => {
debouncedValue.value = newValue
timeoutId = null
}, delay)
}, { immediate: true })
onUnmounted(() => {
if (timeoutId) {
clearTimeout(timeoutId)
}
})
return debouncedValue
}
// App.vue (or any component)
<script setup>
import { ref, watch } from 'vue'
import { useDebounce } from './composables/useDebounce'
const searchTerm = ref('')
const debouncedSearchTerm = useDebounce(searchTerm, 500)
// Simulate an API call
const searchResults = ref([])
async function performSearch(query) {
if (query.trim() === '') {
searchResults.value = []
return
}
// In a real app, this would be an actual API call
console.log(`Performing search for: "${query}"`)
searchResults.value = [`Result for ${query} A`, `Result for ${query} B`]
}
// Watch the debounced value to trigger the search
watch(debouncedSearchTerm, (newVal) => {
performSearch(newVal)
}, { immediate: true })
</script>
<template>
<div>
<h1>Debounced Search Example</h1>
<input
type="text"
v-model="searchTerm"
placeholder="Type to search..."
style="width: 300px; padding: 8px; font-size: 16px;"
/>
<p>Search Term (live): {{ searchTerm }}</p>
<p>Search Term (debounced): {{ debouncedSearchTerm }}</p>
<h2>Search Results:</h2>
<ul v-if="searchResults.length">
<li v-for="result in searchResults" :key="result">{{ result }}</li>
</ul>
<p v-else>No results or type to search.</p>
</div>
</template>
How it works: This snippet provides a reusable Vue 3 composable, `useDebounce`, to delay the execution of a function or update of a reactive value until a specified amount of time has passed without any further changes. This is incredibly useful for optimizing performance in scenarios like search inputs, preventing excessive API calls on every keystroke. The composable takes a `ref` and a `delay`, returning a new `ref` whose value only updates after the `delay` has elapsed since the last change to the input `ref`. It also handles cleanup with `onUnmounted` to prevent memory leaks.