- 问题:如何一次性渲染十万条数据还能保证页面不卡顿
- 思路:直接全部渲染这些数据,会导致页面卡顿,用户体验不佳
- 解决:
- 虚拟列表:只渲染视口可见的部分数据,其余部分在需要时动态加载
- 懒加载:分批次渲染数据
- 分页:分页,每次只显示一页的数据
<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>