通过vue3自定义指令,实现滚动加载大量数据

本文介绍了在前端开发中,当需要一次性加载大量数据时如何通过使用Vue的自定义指令`myscrrol`,结合滚动监听和数据截取策略,优化页面渲染性能,仅显示视口中可见的数据,有效降低绘制成本。
摘要由CSDN通过智能技术生成

使用场景

当前端需要一次性加载大量数据,又不能分页时,如果将几百上千条数据一次性加载到页面中,将会出现卡顿现象,此时的优化方案是对数据进行截取显示滚动到的数据,未滚动到的和已经滚动出视口的可以去除,页面中只显示十几二十条数据,就不会对渲染造成太大的负担。,为了简化过程使用更友好,通过自定义指令来实现

效果

image.png

实现

//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条数据,可以极大的减少绘制成本

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值