Vue2中使用自定义指令实现el-table虚拟列表的代码示例

 更新时间:2025年01月15日 09:29:48   作者:程序员张张  
在实际开发中,我们可能会面临其他需求,例如在 el-table 中无法使用分页技术的情况下展示海量数据,这种情况下,页面可能会出现卡顿,严重时甚至可能引发浏览器崩溃,所以针对这个问题本文给大家介绍了vue2中使用自定义指令实现el-table虚拟列表,需要的朋友可以参考下

引言

上一篇文章我们讲了虚拟列表的实现原理,以及在vue3中的使用实例,感兴趣的友友们可以查看相关内容 传送门。然而,在实际开发中,我们可能会面临其他需求,例如在 el-table 中无法使用分页技术的情况下展示海量数据。这种情况下,页面可能会出现卡顿,严重时甚至可能引发浏览器崩溃。针对这一问题,我们需要寻找其他的解决方案。

创建virtualTable组件

首先新建一个virtualTable.vue文件,代码如下:

<template>
  <div style="width: 100%">
    <el-table v-virtual-list="virtual" width="100%" height="600" :data="tableData.slice(start, over)">
      <el-table-column align="center" prop="date" label="日期" :height="virtual.itemHeight" min-width="180"></el-table-column>
      <el-table-column align="center" prop="name" label="姓名" :height="virtual.itemHeight" min-width="180"></el-table-column>
      <el-table-column align="center" prop="address" label="地址" :height="virtual.itemHeight" min-width="180"></el-table-column>
    </el-table>
  </div>
</template>

<script>
let timeout = null
export default {
  name: 'virtualTable',
  data() {
    return {
      tableData: [],
      virtual: {
        itemHeight: 40, // 每一项高度
        scrollClass: '.el-table__body-wrapper', // 有滚动条元素
        scrollTop: 0, // 滚动条距离顶部距离
        tableHeight: 0 // 可视区高度
      }
    }
  },
  computed: {
    // 起始下标
    start() {
      return Math.max(Math.ceil(this.virtual.scrollTop / this.virtual.itemHeight - 5), 0)
    },
    // 结束下标
    over() {
      return Math.min(
        Math.ceil((this.virtual.scrollTop + this.virtual.tableHeight + 1) / this.virtual.itemHeight + 5),
        this.tableData.length
      )
    },
    // 为了保持列表高度完整且滚动条能正常滚
    paddingAttr() {
      let bottom = (this.tableData.length - this.over) * this.virtual.itemHeight
      let top = this.start * this.virtual.itemHeight
      return `${top}px 0 ${bottom}px 0`
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      let _arr = []
      for (let i = 1; i <= 100000; i++) {
        _arr.push({
          date: '2016-05-02',
          name: '王小虎' + i,
          address: `上海市普陀区金沙江路 ${i} 弄`
        })
      }
      this.tableData = _arr
      timeout = setTimeout(() => {
        const target = document.querySelector(this.virtual.scrollClass)
        this.virtual.tableHeight = target.clientHeight ?? 0
        this.setPaddingAttr(target)
      })
    },
    // 更新padding属性
    setPaddingAttr(target) {
      let _table = target.querySelector('table')
      _table.style.padding = this.paddingAttr
    }
  },
  beforeDestroy() {
    clearTimeout(timeout)
  }
}
</script>

<style scoped>
::v-deep th,
::v-deep td {
  height: 40px;
  line-height: 40px;
  padding: 0;
}
</style>

代码介绍

这边重点说一下里面的关键代码,具体原理可以参考我上一篇文章 传送门

  • virtual对象

virtual对象虚拟列表相关的属性,放在一个对象中方便管理,需要传入到自定义指令中。

  • timeout = setTimeout(() => {})

为了解决组件初始化时nextTick中无法获取到正确的clientHeight

  • this.virtual.tableHeight = target.clientHeight ?? 0

组件初始化时获取容器的可视区高度。

  • this.setPaddingAttr(target)

设置paddingAttr方法,重新计算padding,为了确保虚拟列表的渲染效果正确。

tips

当然这里我们可以将其封装成一个公共的组件,如果有相同的需求直接使用当前组件。这里我就不去封装了,感兴趣的友友们可以去尝试一下。

添加自定义指令

// 虚拟列表自定义指令
Vue.directive('virtual-list', {
  bind(el, bind, vNode) {
    const that = vNode.context
    let virtual = bind.value
    if (virtual) {
      let target = el.querySelector(virtual.scrollClass)
      target.addEventListener('scroll', () => {
        // 更新滚动条位置
        that.virtual.scrollTop = target.scrollTop
        // 重新计算padding
        that.setPaddingAttr(target)
      })
    }
  }
})

关键代码介绍

  • const taht = vNode.context

获取当前指令所在组件的上下文this,以便在后续的代码中访问组件的方法和数据。

  • let virtual = bind.value

获取组件中传入的值,内部包含虚拟列表的相关信息。

  • target.addEventListener('scroll', () => {...})

给容器添加滚动监听事件,当用户滚动时触发该事件。

  • that.virtual.scrollTop = target.scrollTop

更新组件中的 virtual.scrollTop 属性,记录当前滚动条的位置。

  • that.setPaddingAttr(target)

该方法由当前指令所在组件内部提供。重新计算padding,为了确保虚拟列表的渲染效果正确。

最终效果如下:

tips

该自定义指令不仅可以在 el-table 中实现虚拟列表,还可以在 el-select 等组件中使用。在实际开发中,只要了解其原理,就可以有效地应用于实际操作中。

文章小尾巴

以上就是Vue2中使用自定义指令实现el-table虚拟列表的代码示例的详细内容,更多关于Vue2 el-table虚拟列表的资料请关注脚本之家其它相关文章!

相关文章

  • vue-router相关基础知识及工作原理

    vue-router相关基础知识及工作原理

    这篇文章主要介绍了vue-router相关基础知识及单页面应用的工作原理,需要的朋友可以参考下
    2018-03-03
  • vue+iview 实现可编辑表格的示例代码

    vue+iview 实现可编辑表格的示例代码

    这篇文章主要介绍了vue+iview 实现可编辑表格的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • vue在使用element组件出现<el-input>标签无法输入的问题

    vue在使用element组件出现<el-input>标签无法输入的问题

    这篇文章主要介绍了vue在使用element组件出现<el-input>标签无法输入的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • html中创建并调用vue组件的几种方法汇总

    html中创建并调用vue组件的几种方法汇总

    这篇文章主要介绍了html中创建并调用vue组件的几种方法汇总,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下
    2020-11-11
  • 关于Element table组件滚动条不显示的踩坑记录

    关于Element table组件滚动条不显示的踩坑记录

    这篇文章主要介绍了关于Element table组件滚动条不显示的踩坑记录,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 关于vue中输入框的使用场景总结

    关于vue中输入框的使用场景总结

    这篇文章主要介绍了关于vue中输入框的使用场景总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • 使用自动导入后eslint报错eslint9的问题及解决方法

    使用自动导入后eslint报错eslint9的问题及解决方法

    本文介绍了使用`pnpm create vue@latest`创建Vue应用时,如何配置ESLint和Prettier,包括解决两者冲突以及自动导入后Eslint报错的问题,感兴趣的朋友一起看看吧
    2025-03-03
  • vue实现的请求服务器端API接口示例

    vue实现的请求服务器端API接口示例

    这篇文章主要介绍了vue实现的请求服务器端API接口,结合实例形式分析了vue针对post、get、patch、put等请求的封装与调用相关操作技巧,需要的朋友可以参考下
    2019-05-05
  • Vue项目优化打包之前端必备加分项

    Vue项目优化打包之前端必备加分项

    相信现在很多人都是用Vue做过了各种项目,但是项目代码做完和上线并不代表这结束,还有上线以后的优化也是很重要的一点,这篇文章主要给大家介绍了关于Vue项目优化打包的相关资料,需要的朋友可以参考下
    2021-09-09
  • vue渲染时闪烁{{}}的问题及解决方法

    vue渲染时闪烁{{}}的问题及解决方法

    v-if和v-show可能是日常开发中最常用的两个指令,虽然看上去两者功能是类似的,但是两者还是存在很大区别的。接下来通过本文给大家分享vue渲染时闪烁{{}}的问题及解决方法,感兴趣的朋友一起看看吧
    2018-03-03

最新评论