使用场景
当前端需要一次性加载大量数据,又不能分页时,如果将几百上千条数据一次性加载到页面中,将会出现卡顿现象,此时的优化方案是对数据进行截取显示滚动到的数据,未滚动到的和已经滚动出视口的可以去除,页面中只显示十几二十条数据,就不会对渲染造成太大的负担。,为了简化过程使用更友好,通过自定义指令来实现
效果
实现
//reactive.js
import { ref } from 'vue'
let num = ref(0);
let start = ref(0);
let over = ref(15)
export default {
install(app) {
app.directive('myscrrol', {
mounted(el, binding) {
let target = el.querySelector('.el-scrollbar__wrap') //获取滚动元素,并在下面做滚动监听
target.addEventListener('scroll', () => {
// console.log('滚动监听')
// scrrollTop 视口到滚动顶部的高度
// clientHeight 视口到视口的高度
// scrollHeight 可滚动的内容总高度
console.log(num);
start.value = Math.ceil(Math.max(target.scrollTop / 39.67 - 5, 0)) //能显示的开始是第几条
over.value = Math.ceil(Math.min((target.scrollTop + target.clientHeight) / 39.67 + 5, num)) //当前显示的最后一条是
//console.log(target.scrollTop)
})
},
updated(el, binding) {
let target = el.querySelector('.el-scrollbar__wrap')
const _table = target.querySelector('table')
num = binding.value //自定义指令接收到的数据
_table.style.paddingTop = start.value * 39.67 + 'px' //通过padding 将盒子撑起来, 上面用paddingBottom,
_table.style.paddingBottom = (num - over.value) * 39.67 + 'px' 下面用paddingBottom
设置完成为真实的高度
}
})
}
}
export {
start, over
}
注册
// import './assets/main.css'
import '@/assets/main.scss'
import { createApp } from 'vue'
import pinia from '@/stores/index'
import App from './App.vue'
import router from './router'
import scroll from '@/directive' 引入scroll
const app = createApp(App)
app.use(pinia)
app.use(router)
app.use(scroll)
app.mount('#app')
组件中使用
// num 是数据条数,此时将数据传给自定义指令
<template>
<div>{{ start }}----{{ over }}
<el-table v-myscrrol="num" :data="dataList.slice(start, over)" height="300" style="width: 80%">
<el-table-column prop="id" label="id" width="180" />
<el-table-column prop="num" label="num" width="180" />
<el-table-column prop="address" label="address" />
</el-table>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { start, over } from '@/directive'
let dataList = ref([])
let num = ref(0)
console.log(start, over);
onMounted(() => {
let arr = []
for (let i = 1; i <= 250; i++) {
arr.push({
id: i,
num: 200 + i * 10,
address: '课本' + i
})
}
dataList.value = arr
num.value = dataList.value.length
})
</script>
效果
此时列表并没有去全部加载,上图
此时并没有250条数据,可以极大的减少绘制成本