Skip to main content
You are viewing Pre-Alpha documentation.
Vuetify0 Logo
Theme
Mode
Accessibility
Vuetify
Vuetify One

Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

useLazy

A composable for deferring content rendering until first activation, with optional reset on deactivation.

Usage

The useLazy composable tracks whether content has been activated at least once. Content renders only after first activation (unless eager mode is enabled), reducing initial render cost for components like dialogs, menus, and tooltips.

isBooted: false · hasContent: false

<script setup lang="ts">
  import { useLazy } from '@vuetify/v0'
  import { shallowRef, watch } from 'vue'

  const isOpen = shallowRef(false)
  const { hasContent, isBooted, onAfterLeave } = useLazy(isOpen)

  // Simulate loading heavy content
  const isLoading = shallowRef(false)
  const items = shallowRef<string[]>([])

  watch(hasContent, value => {
    if (value && items.value.length === 0) {
      isLoading.value = true
      setTimeout(() => {
        items.value = Array.from({ length: 50 }, (_, i) => `Item ${i + 1}`)
        isLoading.value = false
      }, 800)
    }
  })

  watch(isBooted, value => {
    if (!value) items.value = []
  })
</script>

<template>
  <div>
    <div class="text-center">
      <button
        class="px-4 py-2 bg-primary text-on-primary rounded"
        @click="isOpen = !isOpen"
      >
        {{ isOpen ? 'Close' : 'Open' }}
      </button>
    </div>

    <Transition
      enter-active-class="transition-opacity"
      enter-from-class="opacity-0"
      leave-active-class="transition-opacity"
      leave-to-class="opacity-0"
      @after-leave="onAfterLeave"
    >
      <div
        v-if="isOpen"
        class="mt-4 p-4 bg-surface border border-divider rounded shadow-lg"
      >
        <template v-if="hasContent">
          <div v-if="isLoading" class="py-8 text-center text-on-surface-variant">
            Loading content...
          </div>

          <div v-else class="h-48 overflow-auto">
            <div
              v-for="item in items"
              :key="item"
              class="px-2 py-1 border-b border-divider last:border-b-0"
            >
              {{ item }}
            </div>
          </div>
        </template>
      </div>
    </Transition>

    <p class="mt-4 text-xs text-on-surface-variant text-center">
      isBooted: {{ isBooted }} · hasContent: {{ hasContent }}
    </p>
  </div>
</template>

Architecture

useLazy Lifecycle

Use controls to zoom and pan. Click outside or press Escape to close.

useLazy Lifecycle

Reactivity

Property/MethodReactiveNotes
isBootedShallowRef, readonly
hasContentComputed from isBooted || eager || active
activeAccepts MaybeRefOrGetter, watched for changes
eagerAccepts MaybeRefOrGetter in options

API Reference

The following API details are for the useLazy composable.

Functions

useLazy

(active: MaybeRefOrGetter<boolean>, options?: LazyOptions) => LazyContext

Deferred content rendering for performance optimization.

Options

eager

MaybeRefOrGetter<boolean>

When true, content renders immediately without waiting for activation.

Default: false

Properties

isBooted

Readonly<ShallowRef<boolean>>

Whether the lazy content has been activated at least once.

hasContent

Readonly<Ref<boolean, boolean>>

Whether content should be rendered. True when: isBooted OR eager OR active

Methods

reset

() => void

Reset booted state. Call on leave transition if not eager.

onAfterLeave

() => void

Transition callback for after-leave. Resets if not eager.

Eager Mode

Use the eager option to render content immediately without waiting for activation:

ts
const { hasContent } = useLazy(isOpen, { eager: true })
// hasContent.value is always true

The eager option accepts a reactive value for dynamic control:

ts
const props = defineProps<{ eager: boolean }>()
const { hasContent } = useLazy(isOpen, {
  eager: toRef(() => props.eager),
})

Transition Integration

The onAfterLeave callback resets the lazy state after the leave transition completes (unless eager mode is enabled):

vue
<template>
  <Transition @after-leave="onAfterLeave">
    <div v-if="isOpen">
      <template v-if="hasContent">
        <!-- Heavy content -->
      </template>
    </div>
  </Transition>
</template>

This allows memory to be reclaimed when the content is hidden, while preserving the content during the leave animation.

Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/