Skip to content

VueUse Usage Style

Introduction

VueUse is a collection of useful composables for Vue.js. This guide explains how to use them correctly.

Installation and Setup

Installation

bash
npm install @vueuse/core

Basic Usage

javascript
import { useLocalStorage, useMouse } from '@vueuse/core'

Commonly Used Composables

useLocalStorage

For storing data in localStorage:

javascript
import { useLocalStorage } from '@vueuse/core'

// Simple usage
const count = useLocalStorage('count', 0)

// With advanced settings
const user = useLocalStorage('user', null, {
  serializer: {
    read: (v) => JSON.parse(v),
    write: (v) => JSON.stringify(v)
  }
})

useMouse

For tracking mouse position:

javascript
import { useMouse } from '@vueuse/core'

const { x, y } = useMouse()

// Usage in template
// <div>Mouse position: {{ x }}, {{ y }}</div>

useWindowSize

For tracking window size:

javascript
import { useWindowSize } from '@vueuse/core'

const { width, height } = useWindowSize()

// responsive design
const isMobile = computed(() => width.value < 768)

useFetch

For HTTP requests:

javascript
import { useFetch } from '@vueuse/core'

const { data, error, isLoading } = await useFetch('/api/users')

// With settings
const { data: posts } = await useFetch('/api/posts', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
})

useDebounceFn

For debouncing functions:

javascript
import { useDebounceFn } from '@vueuse/core'

const debouncedSearch = useDebounceFn((query) => {
  // search in API
  searchAPI(query)
}, 300)

// Usage
const handleInput = (event) => {
  debouncedSearch(event.target.value)
}

useThrottleFn

For throttling functions:

javascript
import { useThrottleFn } from '@vueuse/core'

const throttledScroll = useThrottleFn(() => {
  // handle scroll
  console.log('scrolled')
}, 100)

// Usage in event listener
window.addEventListener('scroll', throttledScroll)

Composables for Forms

useVModel

For two-way v-model:

javascript
import { useVModel } from '@vueuse/core'

// in child component
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const value = useVModel(props, 'modelValue', emit)

useForm

For form management:

javascript
import { useForm } from '@vueuse/core'

const { data, errors, validate, reset } = useForm({
  username: '',
  email: '',
  password: ''
})

const handleSubmit = async () => {
  const { valid } = await validate()
  if (valid) {
    // submit form
  }
}

Composables for Animation

useTransition

For smooth animations:

javascript
import { useTransition } from '@vueuse/core'

const source = ref(0)
const output = useTransition(source)

// gradual change
source.value = 100

useSpring

For spring animations:

javascript
import { useSpring } from '@vueuse/core'

const target = ref(0)
const spring = useSpring(target, {
  stiffness: 0.1,
  damping: 0.8
})

Best Practices

Performance

  • Use shallowRef for large data
  • Use computed for complex calculations
  • Use watchEffect for side effects

Error Handling

javascript
import { useFetch } from '@vueuse/core'

const { data, error, isLoading } = await useFetch('/api/data')

// Error handling
if (error.value) {
  console.error('Error fetching data:', error.value)
}

Cleanup

javascript
import { onUnmounted } from 'vue'
import { useEventListener } from '@vueuse/core'

const stop = useEventListener(window, 'resize', handleResize)

// cleanup on unmount
onUnmounted(() => {
  stop()
})

Practical Examples

Counter Component with localStorage

vue
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
    <button @click="reset">Reset</button>
  </div>
</template>

<script setup>
import { useLocalStorage } from '@vueuse/core'

const count = useLocalStorage('counter', 0)

const increment = () => {
  count.value++
}

const reset = () => {
  count.value = 0
}
</script>

Search Component with debounce

vue
<template>
  <div>
    <input 
      v-model="searchQuery" 
      placeholder="Search..."
      @input="handleSearch"
    />
    <div v-if="isLoading">Loading...</div>
    <div v-else>
      <div v-for="result in searchResults" :key="result.id">
        {{ result.title }}
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { useDebounceFn, useFetch } from '@vueuse/core'

const searchQuery = ref('')

const debouncedSearch = useDebounceFn(async (query) => {
  if (query.trim()) {
    const { data } = await useFetch(`/api/search?q=${query}`)
    searchResults.value = data.value
  }
}, 300)

const handleSearch = () => {
  debouncedSearch(searchQuery.value)
}
</script>