【study】如何一次性渲染十万条数据还能保证页面不卡顿

201 阅读1分钟
  1. 问题:如何一次性渲染十万条数据还能保证页面不卡顿
  2. 思路:直接全部渲染这些数据,会导致页面卡顿,用户体验不佳
  3. 解决:
  • 虚拟列表:只渲染视口可见的部分数据,其余部分在需要时动态加载
  • 懒加载:分批次渲染数据
  • 分页:分页,每次只显示一页的数据
// 虚拟列表:在 Vue.js 项目中,可以使用 `vue-virtual-scroller` 库来实现虚拟列表。
// 安装:npm install vue-virtual-scroller


<template>
  <div>
    <RecycleScroller
      :items="items"
      :item-size="50"
      key-field="id"
      class="scroller"
    >
      <template #default="{ item, index }">
        <div class="item">
          {{ index }} - {{ item.text }}
        </div>
      </template>
    </RecycleScroller>
  </div>
</template>

<script>
import { RecycleScroller } from 'vue-virtual-scroller';
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';

export default {
  components: {
    RecycleScroller
  },
  data() {
    return {
      items: Array.from({ length: 100000 }).map((_, index) => ({
        id: index + 1,
        text: `Item ${index + 1}`
      }))
    };
  }
};
</script>

<style>
.scroller {
  height: 600px; /* 设置一个容器高度 */
  overflow-y: auto;
}
.item {
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid #ccc;
}
</style>

// 懒加载

<template>
  <div>
    <button @click="loadMore">Load More</button>
    <div v-for="(item, index) in visibleItems" :key="index">
      {{ item.text }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [],
      visibleItems: [],
      batchSize: 1000,
      nextBatchIndex: 0
    };
  },
  created() {
    this.items = Array.from({ length: 100000 }).map((_, index) => ({
      id: index + 1,
      text: `Item ${index + 1}`
    }));
    this.loadMore();
  },
  methods: {
    loadMore() {
      const end = this.nextBatchIndex + this.batchSize;
      this.visibleItems.push(...this.items.slice(this.nextBatchIndex, end));
      this.nextBatchIndex = end;
    }
  }
};
</script>
// 分页
<template>
  <div>
    <ul>
      <li v-for="(item, index) in currentPageItems" :key="index">
        {{ item.text }}
      </li>
    </ul>
    <button @click="prevPage" :disabled="currentPage === 1">Previous</button>
    <button @click="nextPage" :disabled="currentPage === totalPages">Next</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [],
      currentPage: 1,
      pageSize: 100,
    };
  },
  computed: {
    totalPages() {
      return Math.ceil(this.items.length / this.pageSize);
    },
    currentPageItems() {
      const start = (this.currentPage - 1) * this.pageSize;
      const end = start + this.pageSize;
      return this.items.slice(start, end);
    }
  },
  created() {
    this.items = Array.from({ length: 100000 }).map((_, index) => ({
      id: index + 1,
      text: `Item ${index + 1}`
    }));
  },
  methods: {
    nextPage() {
      if (this.currentPage < this.totalPages) {
        this.currentPage++;
      }
    },
    prevPage() {
      if (this.currentPage > 1) {
        this.currentPage--;
      }
    }
  }
};
</script>