Skip to content

Virtual vs Plain List Demo

This demo compares one large fixed-height list with virtualization enabled and disabled, adds heavier row markup, and measures how long full list mount and unmount take.

Try it yourself

  • Toggle virtual scrolling on and off to compare rendered row counts directly.
  • Toggle list visibility to compare mount and unmount times between virtual and plain modes.
  • Scroll both modes and inspect how much DOM each mode keeps alive.
  • Use this as quick baseline when explaining why large lists need virtualization.

Virtual scrolling on vs off

Compare heavy fixed-height rows with and without virtualization, then hide the whole list to measure mount and unmount cost.

Rows: 10000Mode: virtualRendered rows: 0Mount: —Unmount: —

Source code

vue
<script setup lang="ts">
import { computed, ref } from 'vue'
import { RecycleScroller } from 'vue-virtual-scroller'
import { createSimpleStrings } from '../.vitepress/components/demos/demo-data'

const ITEM_SIZE = 152
const rows = createSimpleStrings(10000, 808)
const showList = ref(true)
const useVirtualScrolling = ref(true)
const mountDuration = ref<number | null>(null)
const unmountDuration = ref<number | null>(null)
const modeLabel = computed(() => useVirtualScrolling.value ? 'virtual' : 'plain')
</script>

<template>
  <RecycleScroller
    v-if="showList && useVirtualScrolling"
    :items="rows"
    :item-size="ITEM_SIZE"
  >
    <template #default="{ item, index }">
      <div :style="{ height: `${ITEM_SIZE}px` }">
        {{ index + 1 }}. {{ item }}
      </div>
    </template>
  </RecycleScroller>

  <div v-else-if="showList">
    <div
      v-for="(item, index) in rows"
      :key="`${index}:${item}`"
      :style="{ height: `${ITEM_SIZE}px` }"
    >
      {{ index + 1 }}. {{ item }}
    </div>
  </div>

  <p>Mode: {{ modeLabel }}</p>
  <p>Mount: {{ mountDuration }}</p>
  <p>Unmount: {{ unmountDuration }}</p>
</template>

Released under the MIT License.