vue3实现多个表格同时滚动并固定表头

 更新时间:2024年02月03日 10:03:36   作者:℘团子এ  
这篇文章主要给大家介绍了vue3中多个表格怎么同时滚动并且固定表头,文中通过代码示例给大家讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下

说明:这里需分为两种情况来做。第一种亲情况就是没有修改过el-table这个组件的样式;第二种情况就是修改过el-table组件的样式。第一种较为简单就简单略过,这里主要提及第二种做法。

1.需求效果

2.第一种没有修改过el-table这个组件的样式的做法

(1)直接看大佬vue2的做法

element ui 实现多个table同时滚动,横向纵向滚动

代码如下:

<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/element-ui@2.15.6/lib/index.js"></script>
<div id="app">
<template>
    <el-table
      ref="table1"
      border="10"
      height="150"
      :data="tableData"
      style="width: 800px">
      <el-table-column
        prop="date"
        label="日期"
        width="300">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名"
        width="300">
      </el-table-column>
      <el-table-column
        width="300px"
        prop="address"
        label="地址">
      </el-table-column>
            <el-table-column
        width="300px"
        prop="address"
        label="地址">
      </el-table-column>
    </el-table>
    

    <el-table
      ref="table2"
      border="10"
      height="150"
      :data="tableData"
      style="width: 800px">
      <el-table-column
        prop="date"
        label="日期"
        width="300">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名"
        width="300">
      </el-table-column>
      <el-table-column
        width="300px"
        prop="address"
        label="地址">
      </el-table-column>
            <el-table-column
        width="300px"
        prop="address"
        label="地址">
      </el-table-column>
    </el-table>
  </template>
</div>
var Main = {
      data() {
        return {
          tableData: [{
            date: '2016-05-02',
            name: '王小虎',
            address: '上海市'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市'
          }],
          dom1: null,
          dom2: null
        }
      },
      mounted() {
        this.dom1 = this.$refs.table1.bodyWrapper
        this.dom2 = this.$refs.table2.bodyWrapper

        this.listenerScroll()
      },
      methods: {
        listenerScroll() {
          this.dom2.addEventListener('scroll', () => {
            // 横滚
            this.dom1.scrollLeft = this.dom2.scrollLeft
            // 竖滚
            this.dom1.scrollTop = this.dom2.scrollTop
          })
        }
      }
    }
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')


(2)以下是vue3写法(可以直接使用看看效果,没效果的就看第二种方法)

<template>
  <div>
      <el-table ref="table1" :data="tableData" style="width: 100%; margin-bottom: 20px" height="200px">
          <el-table-column prop="date" label="Date" width="180"></el-table-column>
          <el-table-column prop="name" label="Name" width="180"></el-table-column>
      </el-table>
      <el-table ref="table2" :data="tableData" style="width: 100%" height="200px">
          <el-table-column prop="address" label="Address" width="180"></el-table-column>
          <el-table-column prop="tag" label="Tag" width="180"></el-table-column>
      </el-table>
  </div>
</template>
 
<script setup>
import { ref, onMounted } from 'vue'
import { ElTable } from 'element-plus'
const table1 = ref(null)
const table2 = ref(null)
let overElement = ""
onMounted(() => {
  const table1Wrapper = table1.value.$refs.bodyWrapper
  const table2Wrapper = table2.value.$refs.bodyWrapper
  console.log("table1Wrapper",table1Wrapper);
  table1Wrapper.addEventListener('mouseover', () => {
      overElement = "a"
      console.log("overElement1",overElement);
  })
  table2Wrapper.addEventListener('mouseover', () => {
      overElement = "b"
      console.log("overElement2",overElement);
  })
  table1Wrapper.addEventListener('scroll', () => {
      console.log("overElement3",overElement);
      if (overElement === "a") {
      console.log("overElement4",overElement);
          table2Wrapper.scrollTop = table1Wrapper.scrollTop
      }
  })
  table2Wrapper.addEventListener('scroll', () => {
      console.log("overElement5",overElement);
      if (overElement === "b") {
      console.log("overElement6",overElement);
          table1Wrapper.scrollTop = table2Wrapper.scrollTop
      }
  })
})
const tableData = [
  {
      date: '2016-05-03',
      name: 'Tom',
      address: 'No. 189, Grove St, Los Angeles',
      tag: 'Home',
  },
  {
      date: '2016-05-02',
      name: 'Tom',
      address: 'No. 189, Grove St, Los Angeles',
      tag: 'Office',
  },
  {
      date: '2016-05-04',
      name: 'Tom',
      address: 'No. 189, Grove St, Los Angeles',
      tag: 'Home',
  },
  {
      date: '2016-05-01',
      name: 'Tom',
      address: 'No. 189, Grove St, Los Angeles',
      tag: 'Office'
  }
]
</script>

3.第二种修改过el-table组件的样式

(1)我这里是修改过el-table的滚动条样式

(2)以下没修改过的

(3)原因分析

从上面两张图片可以看出,它们区别在于输出的(table1Wrapper )第二级一个事table标签,一个不是table标签。所以像第二种修改过el-table组件样式的就不再适用第一种的写法,因为没有拿对节点,要拿的节点不再是.el-table__body-wrapper而是.el-scrollbar__wrap,其他写法就与第一种写法无异。

(4)实现代码

<div>
    <el-table :data="tableData" id="table1" @selection-change="handleSelect" border height="40vh" scrollbar-always-on>
        <el-table-column width="60" fixed type="selection" />>
        <el-table-column width="120" prop="omsCostItemDto.costName" label="计费项名称" />
        <el-table-column prop="omsCostItemDto.profit" label="利润" />
        <el-table-column width="100" prop="omsCostItemDto.merchandiser" label="跟单员" />
    </el-table>
    <el-table :data="tableData" id="table2" border height="40vh" scrollbar-always-on>
        <el-table-column width="120" prop="omsReceiveDto.writeOffAmount" label="核销金额" />
        <el-table-column width="120" prop="omsReceiveDto.notReceivedAmount" label="未收金额" />
        <el-table-column width="180" prop="omsReceiveDto.receiveCreateDate" label="账单生成时间" />
    </el-table>
    <el-table :data="tableData" id="table3" border height="40vh" scrollbar-always-on>
        <el-table-column width="180" prop="omsPayDto.serviceProvidersName" label="服务商名称" class-name="unconfirmed" />
        <el-table-column width="180" prop="omsPayDto.meetName" label="应付企业名称" />
    </el-table>
</div>
onMounted(() => {
    getList(); // 获取列表数据
 
    setTimeout(() => { // 实现同步竖向滚动
        nextTick(() => {
            let table1Wrapper = document.getElementById('table1').getElementsByClassName('el-scrollbar__wrap')[0]
            let table2Wrapper = document.getElementById('table2').getElementsByClassName('el-scrollbar__wrap')[0]
            let table3Wrapper = document.getElementById('table3').getElementsByClassName('el-scrollbar__wrap')[0]
            console.log("table1Wrapper",table1Wrapper);
            table1Wrapper.addEventListener('scroll', () => {
                table2Wrapper.scrollTop = table1Wrapper.scrollTop;
                table3Wrapper.scrollTop = table1Wrapper.scrollTop;
            })
            table2Wrapper.addEventListener('scroll', () => {
                table1Wrapper.scrollTop = table2Wrapper.scrollTop;
                table3Wrapper.scrollTop = table2Wrapper.scrollTop;
            })
            table3Wrapper.addEventListener('scroll', () => {
                table1Wrapper.scrollTop = table3Wrapper.scrollTop;
                table2Wrapper.scrollTop = table3Wrapper.scrollTop;
            })
        })
    }, 1000);
})

(5)代码说明

1.为什么要放到onMounted里

可以放在一个方法里,但是也需要放在onMounted,这样就可以监听到滚动事件而不需要用watch来监听

2.为什么要使用setTimeout和nextTick

照理来说使用onMounted声明周期就可以了,因为它的作用是挂在后,数据和节点都已经生成;我这里不知道什么原因不使用setTimeout和nextTick就拿不到节点,数据倒是已生成(可能是我把getList(); // 获取列表数据放在了前面)

3.重点

重点在于document.getElementById('table1').getElementsByClassName('el-scrollbar__wrap')[0]获取正确的节点,第一种情况和第二种情况区别在于怎么拿到对的节点

4.总结

说白会出现第一种情况和第二种情况在于节点没有拿对

最后

以上就是vue3实现多个表格同时滚动并固定表头的详细内容,更多关于vue3表格同时滚动的资料请关注脚本之家其它相关文章!

相关文章

  • 基于vue+h5实现车牌号输入框功能(demo)

    基于vue+h5实现车牌号输入框功能(demo)

    最近开发项目是学校校内车辆超速方面的统计检测方面的系统,在开发过程中发现有个小功能,就是用户移动端添加车牌号,刚开始想着输入框,提交时正则效验一下格式,最后感觉不方便,所以就简单自己手写了一个H5车牌号软键盘,对vue车牌号输入框实现代码感兴趣的朋友一起看看吧
    2025-03-03
  • 在vue3项目中实现国际化的代码示例

    在vue3项目中实现国际化的代码示例

    国际化就是指在一个项目中,项目中的语言可以进行切换(中英文切换),那么在实际项目中是如何实现的呢,本文就给大家详细的介绍实现方法,需要的朋友可以参考下
    2023-07-07
  • vue实现的多页面项目如何优化打包的步骤详解

    vue实现的多页面项目如何优化打包的步骤详解

    这篇文章主要介绍了vue实现的多页面项目如何优化打包的步骤详解,文中通过示例代码以及图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07
  • Vue2使用cube-ui 实现搜索过滤、高亮功能

    Vue2使用cube-ui 实现搜索过滤、高亮功能

    cube-ui 是基于 Vue.js 实现的精致移动端组件库,由于很长一段时间没有学习cube-ui 的功能实现示例代码了,今天通过本文给大家介绍下Vue2使用cube-ui 实现搜索过滤、高亮功能,感兴趣的朋友跟随小编一起看看吧
    2023-01-01
  • vue3父子传值实现弹框功能的示例详解

    vue3父子传值实现弹框功能的示例详解

    这篇文章主要为大家详细介绍了vue3如何利用父子传值实现弹框功能,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • Vue全局监测错误并生成错误日志实现方法介绍

    Vue全局监测错误并生成错误日志实现方法介绍

    在做完一个项目后,之后的维护尤为重要。这时,如果项目配置了错误日志记录,这样能大大减少维护难度。虽然不一定能捕获到全部的错误,但是一般的错误还是可以监测到的。这样就不用测试人员去一遍一遍复现bug了
    2022-10-10
  • 在Vue项目中取消ESLint代码检测的步骤讲解

    在Vue项目中取消ESLint代码检测的步骤讲解

    今天小编就为大家分享一篇关于在Vue项目中取消ESLint代码检测的步骤讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Luckysheet 在vue中离线使用及引入报错的解决方案(推荐)

    Luckysheet 在vue中离线使用及引入报错的解决方案(推荐)

    这篇文章主要介绍了Luckysheet 在vue中离线使用方法及引入报错的解决方案,将dist离线包在项目创建个文件夹放着,然后根据放置的位置在 index.html里面引入,下面通过案例给大家介绍我的项目里面放置的位置,需要的朋友可以参考下
    2022-10-10
  • el-date-picker默认结束为当前时分秒的操作方法

    el-date-picker默认结束为当前时分秒的操作方法

    在element ui中的日期时间选择组件中默认是00:00,现在需求是点击默认结束时间为当前时分秒,查了很多资料写的都不准确 ,今天给大家分享el-date-picker默认结束为当前时分秒的操作方法,感兴趣的朋友一起看看吧
    2024-01-01
  • 栽Vue3中传递路由参数的三种方式

    栽Vue3中传递路由参数的三种方式

    vue 路由传参的使用场景一般都是应用在父路由跳转到子路由时,携带参数跳转,传参方式可划分为 params 传参和 query 传参,本文将给大家介绍如何通过不同方式在 Vue 3 中传递路由参数,需要的朋友可以参考下
    2024-07-07

最新评论