当前位置: 首页 > article >正文

vue2 + iview(view-design) 中封装使用 vxe-table 处理表格渲染大量数据卡顿现象

今天遇到需求,iview组件分页每页100页时候页面卡顿现象严重,改造为使用vxe-table

@cell-mouseenter="handleCellMouseEnter"

@cell-mouseleave="handleCellMouseLeave"

这两个用来处理vxe-table 内容过多鼠标悬浮上去滚动 tooltip直接消失的问题

:scroll-y="{enabled: true, gt: 0}"   开启大量数据优化

理论上限:纵向最大可以支持 30w 行,当 gt 为 0 时为总是启用。

性能优化:纵向虚拟滚动行高越高越流畅,行高设置 row-config.height

注意slot写法需要修改原版iview配置

改成

<template v-slot:examine_name="{ row }">。。。</template>

renderer组件是处理iview的render,  新建renderer.vue文件输入下面的代码
<script>
export default {
  components: {},
  name: 'renderer',
  props: {
    renderContent: {
      type: Function
    },
    scope: {
      type: Object
    }
  },
  render: function(h) {
    const { renderContent, scope } = this
    return renderContent(h, scope)
  },
  data() {
    return {}
  },
  mounted() {},
  methods: {}
}
</script>

<style lang="scss" scoped></style>

使用

import Vue from 'vue'

import vTable from './vTable/index.vue'

Vue.component('vTable', vTable)

旧 : <Table border :columns="table.columns" :data="table.data" :loading="table.loading"> 

                <template slot-scope="{ row }" slot="examine_name"> 。。。</template>

        </Table>

新 :  <vTable :table="table">

                <template v-slot:examine_name="{ row }">。。。</template>

        </vTable>

注意vxe-table  列拖拽宽度可以使用minWidth了, 而iview必须有width

使用列复选框

<vTable :table="table" checkbox @on-selection-change="selectionChange">

不要写{ title: '选中', type: 'selection', align: 'center', width: '70' }

注意不要再写iview的这个了,不然项目就卡死机啦!!!

其他配置项见 Vxe Table v3

完整封装代码

<template>
  <div>
    <!-- :row-config="{ isHover: true }" -->
    <vxe-table
      min-height="95"
      :max-height="maxHeight"
      @checkbox-all="selectChangeEvent"
      @checkbox-change="selectChangeEvent"
      @cell-mouseenter="handleCellMouseEnter"
      @cell-mouseleave="handleCellMouseLeave"
      :tooltip-config="{ enterable: true }"
      :column-config="{ resizable: true }"
      :scroll-y="{ enabled: true, gt: 0 }"
      class="mytable-style"
      :data="table.data"
      border
      :loading="table.loading"
    >
      <vxe-column v-if="index" align="center" type="seq" fixed="left" width="60"></vxe-column>
      <vxe-column v-if="checkbox" align="center" type="checkbox" width="60"></vxe-column>
      <vxe-column
        v-for="(column, index) in table.columns"
        :key="column.key + index"
        :field="column.key"
        :title="column.title"
        :min-width="column.minWidth"
        :width="column.width"
        :fixed="column.fixed"
        :align="column.align"
        :title-suffix="column.titleSuffix"
        :show-overflow="column.key !== 'action' ? 'tooltip' : false"
      >
        <!-- 渲染形式 -->
        <template #default="scope" v-if="column.render">
          <renderer :renderContent="column.render" :scope="scope"></renderer>
        </template>
        <!-- 自定义插槽 -->
        <template #default="scope" v-else-if="column.slot">
          <slot :name="column.slot" :row="scope.row"></slot>
        </template>
      </vxe-column>
    </vxe-table>
  </div>
</template>

<script>
import renderer from './renderer.vue'
export default {
  components: { renderer },
  name: 'vTable',
  props: {
    table: { type: Object, default: () => {} },
    // 使用复选框 on-selection-change
    checkbox: { type: Boolean, default: false },
    // 使用index
    index: { type: Boolean, default: false }
  },
  data() {
    return {
      maxHeight: null,
      // maxHeight: 650,
      timeout_showTooltip: null
    }
  },
  mounted() {},
  methods: {
    selectChangeEvent(val) {
      this.$emit('on-selection-change', val.records)
    },
    // methods
    // vxe-table 的 tooltip 加上滚动条后, tooltip 关闭再打开, 滚动条仍然在之前 tooltip 滚动到的位置
    // 因此给 tooltip 的滚动主体加上 scrollTop 置空
    handleCellMouseEnter({ $table }) {
      // 取 tooltip 实例
      const $tooltip = $table && $table.$refs && $table.$refs.tooltip
      if ($tooltip && $tooltip.$el) {
        // 如果此时设置了 tooltip 要显示但尚未生效, 则延时显示 tooltip , 避免 tooltip 内滚动条还未重置
        // 注意, 此处是"鼠标移入单元格, 即将显示 tooltip"场景, 在此处处理 scrollTop 重置
        // 不在 mouseleave 处理, 是因为 mouseleave 时这两个数据不准, 从一个有 tooltip 的 cell 移动到下一个, 这两个数据仍然是 true , 因此无法做到"鼠标移出单元格, tooltip 即将关闭, 此时重置 scrollTop"
        if ($table.tooltipStore.visible && !$tooltip.visible) {
          // 清除旧延时, 避免快速切换 tooltip 时, tooltip 的滚动条还未重置就显示出来了
          if (this.timeout_showTooltip) {
            clearTimeout(this.timeout_showTooltip)
          }
          // 延时显示 tooltip
          this.delayShowTooltip($tooltip.$el)
        }
      }
    },
    // 延时显示 vxe-table tooltip
    // 因为 tooltipEl 为 display none 状态时设置 scrollTop 无效, 所以先通过 visibility 隐藏 tooltip , 重置 scrollTop 完毕后再恢复 visible
    delayShowTooltip(tooltipEl) {
      // 取 tooltip 滚动主体元素
      const tooltipContentEl = tooltipEl.querySelector('.vxe-table--tooltip-content')
      if (tooltipContentEl) {
        tooltipEl.style.visibility = 'hidden'
        this.timeout_showTooltip = setTimeout(() => {
          tooltipContentEl.scrollTop = 0
          tooltipEl.style.visibility = 'visible'
          this.timeout_showTooltip = null
        }, 600) // 延时 600 是因为 tooltip 默认 enterDelay 为 500 , 低于 500 会因为 tooltip el 尚未 display , 导致 scrollTop 设置仍然无效
      }
    },
    // vxe-table 的 tooltip , 存在"内部滚动条滚动时触发 table 的 mousewheel 事件, 导致 table 主动关闭 tooltip"问题
    // 因此给 tooltip 滚动主体加上 mousewheel stopPropagation , 停止向上传递 mousewheel 事件给 table
    handleCellMouseLeave({ $table }) {
      // 取 tooltip 实例
      const $tooltip = $table && $table.$refs && $table.$refs.tooltip
      if ($tooltip && $tooltip.$el) {
        // 取 tooltip 滚动主体元素
        const tooltipContentEl = $tooltip.$el.querySelector('.vxe-table--tooltip-content')
        if (tooltipContentEl && !tooltipContentEl.onmousewheel) {
          tooltipContentEl.onmousewheel = e => e.stopPropagation()
        }
      }
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep .vxe-header--column {
  background-color: #f0f2f5 !important;
  border-right: 1px solid #dcdee2 !important;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12) !important;
}
::v-deep .vxe-body--column {
  background-image: none !important;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12) !important;
}
::v-deep .vxe-table--tooltip-arrow {
  display: none;
  visibility: hidden;
}
</style>
<style>
/* .vxe-table--render-default .vxe-table--scroll-y-handle, .vxe-table--render-default .vxe-table--scroll-y-virtual{
  right: auto !important;
} */
.vxe-table--tooltip-wrapper {
  max-width: 300px !important;
  max-height: 300px !important;
  overflow-y: auto !important;
  background-color: rgba(70, 76, 91, 0.9) !important;
  color: #fff !important;
  padding: 8px 12px !important;
  font-size: 15px;
}
.vxe-table--tooltip-wrapper.theme--dark.placement--top .vxe-table--tooltip-arrow,
.vxe-table--tooltip-wrapper.theme--dark.placement--top .vxe-table--tooltip-arrow:before {
  display: none;
}
.vxe-table--tooltip-wrapper.placement--top.is--enterable:after {
  bottom: 0px;
}
.vxe-table--empty-content {
  color: #303133;
}
</style>


http://www.kler.cn/a/405436.html

相关文章:

  • 【Stable Diffusion】 超大尺寸绘制、分区控制,详解Tiled Diffusion VAE插件功能
  • python oa服务器巡检报告脚本的重构和修改(适应数盾OTP)有空再去改
  • Linux(命令行扩展+命令行历史 大白话+图片)
  • 合法三元数量计算
  • 图像处理 之 凸包和最小外围轮廓生成
  • 国标GB28181视频平台EasyCVR视频融合平台H.265/H.264转码业务流程
  • 后端返回二进制流前端导出下载excel文件
  • Vue 项目中如何使用FullCalendar 时间段选择插件(类似会议室预定、课程表)
  • VMware虚拟机Ubuntu桥接模式突然连接不上网络解决办法
  • 类文件结构详解.上
  • Linux-Apache静态资源
  • 【SpringBoot】发送各种复杂格式的邮件
  • Centos 8, add repo
  • .net 8使用hangfire实现库存同步任务
  • 分布式锁RedissonClient应用
  • 某车企ASW面试笔试题
  • Linux tcpdump 详解教程
  • 海盗王集成网关和商城服务端功能golang版
  • 重构代码之引入本地扩展
  • 【IOS】编译缓存错误Library/Caches/com.apple.mobile.installd.staging
  • 直流电表精准计量,为光伏产业续航
  • 2025蓝桥杯(单片机)备赛--扩展外设之UART1的原理与应用(十二)
  • 分治法的魅力:高效解决复杂问题的利器
  • 什么是axios?怎么使用axios封装Ajax?
  • 第1章 初识SpringMVC
  • 【滑动窗口】至少有k个重复字符的最长子串