Vấn đề render danh sách lớn

Khi danh sách có hàng nghìn mục, Vue tạo quá nhiều DOM node, gây lag và tăng thời gian paint. Giải pháp: render chỉ những mục hiện ra trên màn hình.

Virtual Scrolling là gì?

Virtual Scrolling (còn gọi là windowing) chỉ tạo DOM cho phần tử trong viewport và một vài buffer. Khi scroll, Vue tái sử dụng các node đã tạo, giảm số lượng node đồng thời.

Cài đặt thư viện vue-virtual-scroller

Sử dụng npm để cài đặt:

npm install vue-virtual-scroller@next

Import trong component:

import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

export default {
  components: { RecycleScroller },
  data() {
    return {
      items: [] // dữ liệu danh sách
    }
  },
  created() {
    // giả lập 10.000 mục
    this.items = Array.from({ length: 10000 }, (_, i) => ({ id: i, text: `Mục ${i + 1}` }))
  }
}

Sử dụng RecycleScroller trong template

Đặt chiều cao container và chiều cao mỗi mục để tính toán.

<template>
  <RecycleScroller
    :items="items"
    :item-size="40"
    height-field="400"
    key-field="id"
    v-slot="{ item }"
  >
    <div class="item" :key="item.id">
      {{ item.text }}
    </div>
  </RecycleScroller>
</template>

Tối ưu thêm với memoization

Nếu mỗi mục có tính toán nặng, dùng computed hoặc watch để cache kết quả. Ví dụ:

computed: {
  processedItems() {
    return this.items.map(item => ({
      ...item,
      heavyResult: this.heavyCalc(item.id)
    }))
  }
},
methods: {
  heavyCalc(id) {
    // giả lập tính toán tốn thời gian
    let sum = 0
    for (let i = 0; i < 10000; i++) sum += i * id
    return sum
  }
}

Kết hợp processedItems với RecycleScroller để chỉ tính toán khi dữ liệu thay đổi, không khi scroll.

Kiểm tra hiệu năng

Dùng Chrome DevTools Performance tab. So sánh thời gian paint và FPS trước và sau khi áp dụng Virtual Scrolling. Thông thường FPS tăng từ ~20 lên ~60 khi danh sách > 5000 mục.

Kết luận

Virtual Scrolling giảm DOM node, cải thiện FPS, giảm bộ nhớ. Kết hợp memoization để tối ưu tính toán mỗi mục.

Muốn học sâu hơn, Tham khảo khóa học "Lập trình Front-End với VueJS Framework" tại đây.