有时候数据过大,会导致页面渲染过慢占用cpu过多,所以需要对数据进行处理
处理方式就是在固定的高度的容器中展示可见的数据,通过控制滚动条来修改数据
<template>
<div class="home">
<RecycleScrollerVue
:items="items"
:item-size="54"
class="scroller"
v-slot="{item}"
>
<ListItemVue :item="item"></ListItemVue>
</RecycleScrollerVue>
</div>
</template>
<script>
// import Simple from '../components/drawer/simple.vue'
import ListItemVue from "./ListItem.vue"
import RecycleScrollerVue from "./RecycleScroller.vue"
var items = [];
for(let i = 0; i < 10000; i++) {
//=> 添加10000条数据
items.push({
id: i + 1,
count: i + 1
})
}
export default {
name: 'Home',
components: {
ListItemVue,
RecycleScrollerVue
},
data() {
return {
items
}
}
}
</script>
<style scoped>
.scroller {
width: 600px;
margin: 0 auto;
height: 500px;
}
</style>
<template>
<div class="list-item">
<span>id{{ item.id }}</span>
<span>count{{ item.count }}</span>
<span>age{{ item.count }}</span>
</div>
</template>
<script>
export default {
props: {
item: Object
}
}
</script>
<style>
.list-item {
text-align: center;
height: 54px;
padding: 1rem;
box-sizing: border-box;
display: grid;
grid-template-columns: repeat(3, 1fr);
box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
}
</style>
<template>
<div class="recycle-scroller-container" @scroll="setPool" ref="container">
<div class="recycle-scroller-wrapper" :style="{height: `${totalSize}px`}">
<div
class="recycle-scroller-item"
v-for="poolItem in pool"
:key="poolItem[keyField]"
:style="{transform: `translateY(${poolItem.position}px)`}"
>
<!-- 作用域插槽 -->
<slot :item="poolItem.item"></slot>
</div>
</div>
</div>
</template>
<script>
// 防止滑动过快出现白板,前面多显示10个,后面也多显示10个(也可配置props)
let prev = 10,
next = 10;
//可回收的使用
export default {
name: 'RecycleScroller',
props: {
items: {
type: Array,
default: () => []
},
// 每条数据的高度
itemSize: {
type: Number,
default: 0
},
keyField: {//以什么作为key值
type: String,
default: 'id'
}
},
mounted() {
// 设置数据池
this.setPool();
window.vm = this;
},
data() {
return {
//{item: 原始数据, position: 该数据的偏移量, }
pool: [],//渲染池,保存当前需要渲染的数据
}
},
computed: {
totalSize() {
return this.items.length * this.itemSize;//计算总高度
}
},
methods: {
setPool() {
// 获取滚动高度,计算前面有多少项不可见
const scrollTop = this.$refs.container.scrollTop
const conHeight = this.$refs.container.clientHeight//容器的高度
console.log(scrollTop)
// 开始下标以及结束下标
let startIndex = Math.floor(scrollTop / this.itemSize)//向下取整
let endIndex = Math.ceil((scrollTop + conHeight)/this.itemSize);//(滚动高度 + 容器高度)/每个子元素的高度
startIndex -= prev;
if(startIndex < 0) {
startIndex = 0
}
endIndex += next//不用处理了因为slice的截取超过了也没用
const startPos = startIndex * this.itemSize//起始下标偏移量
this.pool = this.items.slice(startIndex, endIndex).map((item, i) => ({
item,
position: startPos + i * this.itemSize
}));
}
}
}
</script>
<style>
.recycle-scroller-container {
/* 高度不知道不去设置 */
overflow: auto;
}
.recycle-scroller-wrapper {
position: relative;
}
.recycle-scroller-item {
position: absolute;
width: 100%;
left: 0;
top: 0;
}
</style>
效果图如下: