Skip to content
Back to skills

N Virtual List

ASecurity

Virtual list component for efficient rendering of large lists. Invoke when user needs to implement high-performance lists with thousands of items in Naive UI.

  • 8 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 11, 2026
devopsvueapiperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 11, 2026

npx -y skills add jiaiyan/naive-ui-skills --skill n-virtual-list --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of N Virtual List?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for N Virtual List
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/jiaiyan-n-virtual-list/badge)](https://www.skillsdirectory.com/skills/jiaiyan-n-virtual-list)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "n-virtual-list"
description: "Virtual list component for efficient rendering of large lists. Invoke when user needs to implement high-performance lists with thousands of items in Naive UI."
metadata:
  author: jiaiyan
  version: "1.0.0"
---

# Naive UI Virtual List Component

When it comes to virtual lists, it can feel like a list is infinitely long, but in reality it just secretly hides the invisible elements. Perfect for rendering large datasets efficiently.

## When to Use

Use this component when:
- **Large lists**: Render lists with thousands of items efficiently
- **Chat messages**: Display large message histories
- **Data tables**: Show large datasets without performance issues
- **Infinite scroll**: Implement virtual scrolling for better performance

## When to Invoke

Invoke this skill when:
- User needs to render large lists efficiently
- User wants to implement virtual scrolling
- User needs dynamic item sizes
- User wants to scroll to specific items programmatically
- User asks about performance optimization for large lists

## Features

- **Virtual Rendering**: Only renders visible items for performance
- **Fixed or Dynamic Size**: Support for fixed or dynamic item heights
- **Programmatic Scroll**: Scroll to index, key, or position
- **Keep-alive Support**: Preserve scroll state with keep-alive
- **Resizable Items**: Dynamic item size calculation
- **Scrollbar Integration**: Built-in scrollbar support

## API Reference

### Virtual List Props

| Name | Type | Default | Description |
|------|------|---------|-------------|
| default-scroll-key | `string \| number` | `undefined` | Default scroll key. |
| default-scroll-index | `number` | `undefined` | Default scroll index. |
| ignore-item-resize | `boolean` | `false` | Ignore item resize for slightly better performance. |
| items | `Array<object>` | `[]` | Data to display. |
| item-resizable | `boolean` | `false` | Whether dynamic sizing is enabled. |
| item-size | `number` | required | Minimum height of the item in pixels. |
| items-style | `string \| CSSProperties` | `undefined` | Items container style. |
| key-field | `string` | `'key'` | Field name of option key. |
| padding-top | `string \| number` | `undefined` | Distance from the top. |
| padding-bottom | `string \| number` | `undefined` | Distance from the bottom. |
| scrollbar-props | `ScrollbarProps` | `undefined` | Scrollbar props. |
| visible-items-tag | `string` | `'div'` | Items container tag. |
| visible-items-props | `object` | `undefined` | Items container props. |
| on-scroll | `(event: Event) => void` | `undefined` | Scrolling callback function. |
| on-wheel | `(event: WheelEvent) => void` | `undefined` | Callback for wheel event. |
| on-resize | `(event: ResizeObserverEntry) => void` | `undefined` | Element resizing callback. |

### Virtual List Methods

| Name | Type | Description |
|------|------|-------------|
| scrollTo | `ScrollTo` | Scroll to a position. |

#### ScrollTo Type

```ts
interface ScrollTo {
  (x: number, y: number): void
  (options: {
    left?: number
    top?: number
    behavior?: ScrollBehavior
    debounce?: boolean
  }): void
  (options: {
    index: number
    behavior?: ScrollBehavior
    debounce?: boolean
  }): void
  (options: {
    key: string | number
    behavior?: ScrollBehavior
    debounce?: boolean
  }): void
  (options: {
    position: 'top' | 'bottom'
    behavior?: ScrollBehavior
    debounce?: boolean
  }): void
}
```

## Basic Usage

### Fixed Size Items

```vue
<template>
  <n-virtual-list style="max-height: 240px" :item-size="42" :items="items">
    <template #default="{ item }">
      <div :key="item.key" class="item" style="height: 42px">
        <img class="avatar" :src="item.avatar" alt="">
        <span>{{ item.value }}</span>
      </div>
    </template>
  </n-virtual-list>
</template>

<script setup>
import { ref } from 'vue'

const items = ref(
  Array.from({ length: 1000 }).map((_, i) => ({
    key: i,
    value: `Item ${i}`,
    avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${i}`
  }))
)
</script>

<style scoped>
.item {
  display: flex;
  align-items: center;
}
.avatar {
  width: 28px;
  border-radius: 50%;
  margin-right: 10px;
}
</style>
```

### Dynamic Size Items

```vue
<template>
  <n-virtual-list
    style="max-height: 240px"
    :item-size="42"
    :items="items"
    item-resizable
  >
    <template #default="{ item, index }">
      <div :key="item.key" class="item">
        <img class="avatar" :src="item.avatar" alt="">
        <span>{{ index }} - {{ item.message }}</span>
      </div>
    </template>
  </n-virtual-list>
</template>
```

## Common Patterns

### Scroll to Position

```vue
<template>
  <n-space vertical>
    <n-space>
      <n-button @click="handleScrollToKey">
        Scroll to Key
      </n-button>
      <n-button @click="handleScrollToPosition">
        Scroll to Position
      </n-button>
      <n-button @click="handleScrollToIndex">
        Scroll to Index
      </n-button>
      <n-button @click="handleScrollToDistance">
        Scroll to Distance
      </n-button>
    </n-space>
    <n-virtual-list
      ref="virtualListInst"
      style="max-height: 240px"
      :item-size="42"
      :items="items"
      item-resizable
    >
      <template #default="{ item, index }">
        <div :key="item.key" class="item" style="height: 42px">
          <img class="avatar" :src="item.avatar" alt="">
          <span>{{ index }}</span>
        </div>
      </template>
    </n-virtual-list>
  </n-space>
</template>

<script setup>
import { ref } from 'vue'

const virtualListInst = ref(null)
const items = ref([])

const handleScrollToKey = () => {
  virtualListInst.value?.scrollTo({ key: 500, behavior: 'smooth' })
}

const handleScrollToPosition = () => {
  virtualListInst.value?.scrollTo({ top: 1000, behavior: 'smooth' })
}

const handleScrollToIndex = () => {
  virtualListInst.value?.scrollTo({ index: 200, behavior: 'smooth' })
}

const handleScrollToDistance = () => {
  virtualListInst.value?.scrollTo({ position: 'bottom', behavior: 'smooth' })
}
</script>
```

### Keep State with Keep-alive

```vue
<template>
  <n-space vertical>
    <n-button @click="showVirtualList = !showVirtualList">
      Toggle visibility
    </n-button>
    <keep-alive>
      <n-virtual-list
        v-if="showVirtualList"
        style="max-height: 240px"
        :item-size="42"
        :items="items"
        item-resizable
      >
        <template #default="{ item, index }">
          <div :key="item.key" class="item" style="height: 42px">
            <img class="avatar" :src="item.avatar" alt="">
            <span>{{ index }}</span>
          </div>
        </template>
      </n-virtual-list>
    </keep-alive>
  </n-space>
</template>

<script setup>
import { ref } from 'vue'

const showVirtualList = ref(true)
const items = ref([])
</script>
```

### With Custom Scrollbar

```vue
<template>
  <n-virtual-list
    style="max-height: 240px"
    :item-size="42"
    :items="items"
    :scrollbar-props="{ trigger: 'none', size: 10 }"
  >
    <template #default="{ item, index }">
      <div :key="item.key" style="height: 42px; padding: 8px">
        {{ index }}: {{ item.value }}
      </div>
    </template>
  </n-virtual-list>
</template>
```

### Chat Message List

```vue
<template>
  <n-virtual-list
    ref="chatListRef"
    style="height: 400px"
    :item-size="60"
    :items="messages"
    item-resizable
    :default-scroll-index="messages.length - 1"
  >
    <template #default="{ item }">
      <div :key="item.id" class="message">
        <div class="sender">{{ item.sender }}</div>
        <div class="content">{{ item.content }}</div>
      </div>
    </template>
  </n-virtual-list>
</template>

<script setup>
import { ref } from 'vue'

const messages = ref([
  { id: 1, sender: 'Alice', content: 'Hello!' },
  { id: 2, sender: 'Bob', content: 'Hi there!' }
])
</script>
```

## Best Practices

1. **Set item-size**: Always provide a reasonable `item-size` estimate for better scroll calculation

2. **Use item-resizable**: Enable `item-resizable` when items have variable heights

3. **Unique keys**: Ensure each item has a unique key field

4. **Performance**: Use `ignore-item-resize` if items don't resize for slightly better performance

5. **Keep-alive**: Use keep-alive to preserve scroll state when toggling visibility

6. **Debounce scroll**: Use `debounce: true` in scrollTo for smoother scrolling

7. **Scrollbar props**: Customize scrollbar via `scrollbar-props`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.