Files
gh-lttr-claude-marketplace-…/skills/nuxt/references/vueuse.md
2025-11-30 08:38:06 +08:00

4.7 KiB

VueUse Integration

Check if installed: Look for @vueuse/core or @vueuse/nuxt in package.json before using.

Overview

VueUse is a collection of essential Vue Composition Utilities. It provides ready-made composables for common tasks, eliminating the need to write custom implementations.

Installation Detection

Prefer VueUse over custom implementations when it's installed. Always check package.json first.

Common Composables

State Management

useLocalStorage / useSessionStorage

// Syncs ref with localStorage
const token = useLocalStorage("auth-token", "")
const user = useLocalStorage<User | null>("user", null)

// Automatically saves to localStorage when updated
token.value = "new-token"

useToggle

const [isOpen, toggle] = useToggle()
// toggle() switches between true/false
// toggle(true) sets to true
// toggle(false) sets to false

useCounter

const { count, inc, dec, set, reset } = useCounter(0, { min: 0, max: 10 })

Browser APIs

useMouse

const { x, y, sourceType } = useMouse()
// Reactive mouse position

useWindowSize

const { width, height } = useWindowSize()
// Reactive window dimensions

useScroll

const { x, y, isScrolling, arrivedState, directions } = useScroll(elementRef)
// Track scroll position and state

useClipboard

const { text, copy, copied, isSupported } = useClipboard()

async function copyToClipboard() {
  await copy("Hello World")
  // copied.value is true for 1.5s
}

useMediaQuery

const isMobile = useMediaQuery("(max-width: 768px)")
const isDark = useMediaQuery("(prefers-color-scheme: dark)")

Element Interaction

useIntersectionObserver

const target = ref<HTMLElement | null>(null)
const isVisible = ref(false)

useIntersectionObserver(target, ([{ isIntersecting }]) => {
  isVisible.value = isIntersecting
})

useElementVisibility

const target = ref<HTMLElement | null>(null)
const isVisible = useElementVisibility(target)

useFocus

const input = ref<HTMLInputElement | null>(null)
const { focused } = useFocus(input)

// Auto-focus on mount
useFocus(input, { initialValue: true })

Network

useFetch (VueUse version, different from Nuxt's useFetch)

const { data, error, isFetching } = useFetch("https://api.example.com/users")
  .get()
  .json()

Note: In Nuxt, prefer Nuxt's built-in useFetch for API calls. Use VueUse's useFetch only for external APIs or when you need different behavior.

Utilities

refDebounced / useDebounceFn

// Debounce a ref value
const input = ref("")
const debounced = refDebounced(input, 500)

// Debounce a function
const debouncedFn = useDebounceFn(() => {
  console.log("Debounced!")
}, 500)

refThrottled / useThrottleFn

// Throttle a ref value
const scrollY = ref(0)
const throttled = refThrottled(scrollY, 200)

// Throttle a function
const throttledFn = useThrottleFn(() => {
  console.log("Throttled!")
}, 200)

useInterval / useTimeout

const counter = ref(0)
const { pause, resume } = useInterval(1000, {
  callback: () => counter.value++,
})

useEventListener

useEventListener(window, "resize", () => {
  console.log("Window resized")
})

// On element
const button = ref<HTMLButtonElement | null>(null)
useEventListener(button, "click", () => {
  console.log("Clicked")
})

Nuxt Auto-Import

When using @vueuse/nuxt, composables are auto-imported. No need to import them manually.

// ✅ With @vueuse/nuxt
const { width } = useWindowSize()

// ❌ Without @vueuse/nuxt (need manual import)
import { useWindowSize } from "@vueuse/core"
const { width } = useWindowSize()

Common Patterns

Dark Mode Toggle

const isDark = useDark()
const toggleDark = useToggle(isDark)

Infinite Scroll

const el = ref<HTMLElement | null>(null)
const { arrivedState } = useScroll(el)

watch(
  () => arrivedState.bottom,
  async (isBottom) => {
    if (isBottom) {
      await loadMore()
    }
  },
)

Form Field Debouncing

const searchQuery = ref("")
const debouncedQuery = refDebounced(searchQuery, 300)

watch(debouncedQuery, async (query) => {
  // API call with debounced value
  await searchProducts(query)
})

Responsive Breakpoints

const breakpoints = useBreakpoints({
  mobile: 640,
  tablet: 768,
  laptop: 1024,
  desktop: 1280,
})

const isMobile = breakpoints.smaller("tablet")
const isDesktop = breakpoints.greaterOrEqual("laptop")

Resources