Vxe UI vue vxe-table grid 性能优化,提高渲染性能

news2024/11/29 10:32:48

Vxe UI vue vxe-table vxe-grid 本身就支持虚拟滚动以及灵活的扩展,可也是由于太过灵活,可定制化程度太高,比如单元格自定义渲染,一旦写得不好,就会影响渲染卡顿。

vxe-table 和 vxe-grid

直接使用 vxe-grid,grid 的渲染性能是最优的,全部功能比 table 强非常多。

全局参数

对于不同项目,只需要利用好全局参数,基本上就可以实现无需封装了,基本上所有组件都支持全局参数配置。

整理了最优的全局参数配置:

import { VxeUI } from 'vxe-table'

VxeUI.setConfig({
  version: 0, // 版本号,比如使用了相关的浏览器本地储存功能,当组件升级后系统自动重置数据,那么只需要不断增加版本即可
  zIndex: 2000, // 弹出层的层级,一般设置 2000 就够了
  table: {
    border: true, // 表格边框
    showOverflow: true, // 单元格溢出隐藏,大幅提高渲染性能
    autoResize: true, // 自动根据父容器适应调整宽高
    columnConfig: {
      resizable: true // 列宽拖动调整宽度
    },
    editConfig: {
      trigger: 'click' // 默认点击编辑
    },
    sortConfig: {
      trigger: 'cell' // 默认单元格编辑
    },
    scrollX: {
      enabled: false, // 默认关闭横向虚拟滚动,一般横向使用很少,局部开启就可以
      gt: 15
    },
    scrollY: {
      enabled: true, // 默认启用纵向虚拟滚动
      gt: 20
    }
  },
  // grid 会默认继承 table,所以无需重复设置一样的参数
  grid: {
    toolbarConfig: {
      custom: true // 全局开启自定义列
    },
    // 数据代理相关配置,无使用就忽略
    proxyConfig: {
      showResponseMsg: false,
      showActiveMsg: true,
      response: {
        total: 'page.total',
        result: 'data',
        list: 'data'
      }
    }
  }
})

使用

高度是非常重要的参数,可以固定,也可以设置 100% 自适应父容器,提高渲染性能

一千行渲染
在这里插入图片描述
一万行渲染
在这里插入图片描述
十万行渲染
在这里插入图片描述

<template>
  <div>
    <p>
      <vxe-button @click="loadList(1000)">1k行</vxe-button>
      <vxe-button @click="loadList(5000)">5k行</vxe-button>
      <vxe-button @click="loadList(10000)">1w行</vxe-button>
      <vxe-button @click="loadList(50000)">5w行</vxe-button>
      <vxe-button @click="loadList(100000)">10w行</vxe-button>
    </p>
    <vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
import { VxeUI } from 'vxe-table'
const gridRef = ref()
const gridOptions = reactive({
  border: true,
  showOverflow: true,
  height: 800,
  loading: false,
  scrollY: {
    enabled: true,
    gt: 0
  },
  columns: [
    { type: 'seq', title: '序号', width: 100 },
    { field: 'name', title: 'Name', minWidth: 180 },
    { field: 'role', title: 'Role', width: 200 },
    { field: 'num', title: 'Num', width: 200 },
    { field: 'address', title: 'Address', width: 200 }
  ],
  data: []
})
// 模拟行数据
const loadList = (size = 200) => {
  gridOptions.loading = true
  setTimeout(() => {
    const dataList = []
    for (let i = 0; i < size; i++) {
      dataList.push({
        id: i,
        name: `名称${i} 名称名称 称`,
        role: `role ${i}`,
        num: 20,
        address: 'shenzhen shen'
      })
    }
    const $grid = gridRef.value
    if ($grid) {
      const startTime = Date.now()
      $grid.loadData(dataList).then(() => {
        VxeUI.modal.message({
          content: `加载时间 ${Date.now() - startTime} 毫秒`,
          status: 'success'
        })
        gridOptions.loading = false
      })
    }
  }, 350)
}
loadList(500)

</script>

可编辑

当列比较多时,就可以开启横向虚拟滚动,以下同时使用可编辑+纵向和横向虚拟滚动,极致流畅的渲染表格,同时还能支持任意扩展,单元格任意自定义(需要注意自定义的逻辑是否复杂,过度复杂会影响渲染性能)。

10000行 x 150列
在这里插入图片描述
滚动以及编辑输入都是丝滑流畅的
在这里插入图片描述

<template>
  <div>
    <p>
      <vxe-button @click="loadDataAndColumns(100, 50)">100行50列</vxe-button>
      <vxe-button @click="loadDataAndColumns(1000, 80)">1k行80列</vxe-button>
      <vxe-button @click="loadDataAndColumns(5000, 100)">5k行100列</vxe-button>
      <vxe-button @click="loadDataAndColumns(10000, 150)">1w行150列</vxe-button>
      <vxe-button @click="loadDataAndColumns(30000, 200)">3w行200列</vxe-button>
    </p>
    <p>
      <vxe-button @click="loadDataAndColumns(50, 50)">50行100列</vxe-button>
      <vxe-button @click="loadDataAndColumns(80, 1000)">80行1k列</vxe-button>
      <vxe-button @click="loadDataAndColumns(100, 5000)">100行5k列</vxe-button>
      <vxe-button @click="loadDataAndColumns(150, 10000)">200行1w列</vxe-button>
      <vxe-button @click="loadDataAndColumns(200, 30000)">200行3w列</vxe-button>
    </p>
    <vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue'
import { VxeUI } from 'vxe-table'
const gridRef = ref()
const gridOptions = reactive({
  border: true,
  loading: false,
  showOverflow: true,
  showHeaderOverflow: true,
  showFooterOverflow: true,
  height: 800,
  editConfig: {
    trigger: 'click',
    mode: 'cell'
  },
  scrollY: {
    enabled: true,
    gt: 0
  },
  scrollX: {
    enabled: true,
    gt: 0
  }
})
// 模拟行与列数据
const loadDataAndColumns = (rowSize, colSize) => {
  gridOptions.loading = true
  setTimeout(() => {
    const $grid = gridRef.value
    const colList = []
    for (let i = 0; i < colSize; i++) {
      colList.push({
        field: `col${i}`,
        title: `标题${i}`,
        width: 160,
        editRender: { name: 'VxeInput' }
      })
    }
    const dataList = []
    for (let i = 0; i < rowSize; i++) {
      const item = {
        id: 10000 + i
      }
      for (let j = 0; j < colList.length; j++) {
        item[`col${j}`] = `值_${i}_${j}`
      }
      dataList.push(item)
    }
    if ($grid) {
      const startTime = Date.now()
      $grid.loadColumn(colList).then(() => {
        return $grid.loadData(dataList)
      }).then(() => {
        VxeUI.modal.message({
          content: `加载时间 ${Date.now() - startTime} 毫秒`,
          status: 'success'
        })
        gridOptions.loading = false
      })
    }
  }, 50)
}
onMounted(() => {
  loadDataAndColumns(50, 50)
})

</script>

更复杂的渲染

使用左右冻结列+复杂的单元格渲染、头像、上传图片、全屏预览,开关组件等

以下测试渲染1000-50000行速度
在这里插入图片描述

<template>
  <div>
    <vxe-button @click="loadData(5000)">加载5k条</vxe-button>
    <vxe-button @click="loadData(10000)">加载1w条</vxe-button>
    <vxe-button @click="loadData(50000)">加载5w条</vxe-button>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { reactive, nextTick } from 'vue'
import { VxeUI } from 'vxe-table'
const flag1CellRender = reactive({
  name: 'VxeSwitch'
})
const imgUrlCellRender = reactive({
  name: 'VxeImage',
  props: {
    width: 36,
    height: 36
  }
})
const imgList1CellRender = reactive({
  name: 'VxeUpload',
  props: {
    mode: 'image',
    readonly: true,
    moreConfig: {
      maxCount: 2
    },
    imageStyle: {
      width: 40,
      height: 40
    }
  }
})
const gridOptions = reactive({
  border: true,
  showOverflow: true,
  showHeaderOverflow: true,
  showFooterOverflow: true,
  loading: false,
  height: 800,
  columnConfig: {
    resizable: true
  },
  scrollX: {
    enabled: true,
    gt: 0
  },
  scrollY: {
    enabled: true,
    gt: 0
  },
  columns: [
    { title: '列0', field: 'col0', width: 100, fixed: 'left' },
    { title: '列1', field: 'imgUrl', width: 80, fixed: 'left', cellRender: imgUrlCellRender },
    { title: '列2', field: 'col2', width: 90, fixed: 'left' },
    { title: '列3', field: 'col3', width: 200 },
    { title: '列4', field: 'col4', width: 140 },
    { title: '列5', field: 'col5', width: 300 },
    { title: '列6', field: 'col6', width: 160 },
    { title: '列7', field: 'col7', width: 120 },
    { title: '列8', field: 'col8', width: 400 },
    { title: '列9', field: 'col9', width: 160 },
    { title: '列10', field: 'col10', width: 160 },
    { title: '列11', field: 'col11', width: 180 },
    { title: '列12', field: 'col12', width: 160 },
    { title: '列13', field: 'col13', width: 80 },
    { title: '列14', field: 'col14', width: 120 },
    { title: '列15', field: 'col15', width: 360 },
    { title: '列16', field: 'col16', width: 150 },
    { title: '列17', field: 'col17', width: 380 },
    { title: '列18', field: 'col18', width: 100 },
    { title: '列19', field: 'col19', width: 290 },
    { title: '列20', field: 'col20', width: 80 },
    { title: '列21', field: 'col21', width: 100 },
    { title: '列22', field: 'col22', width: 120 },
    { title: '列23', field: 'col23', width: 270 },
    { title: '列24', field: 'col24', width: 330 },
    { title: '列25', field: 'col25', width: 460 },
    { title: '列26', field: 'col26', width: 280 },
    { title: '列27', field: 'col27', width: 220 },
    { title: '列28', field: 'col28', width: 120 },
    { title: '列29', field: 'col29', width: 180 },
    { title: '列30', field: 'col30', width: 500 },
    { title: '列31', field: 'col31', width: 600 },
    { title: '列32', field: 'col32', width: 100 },
    { title: '列33', field: 'col33', width: 490 },
    { title: '列34', field: 'col34', width: 100 },
    { title: '列35', field: 'col35', width: 150 },
    { title: '列36', field: 'col36', width: 800 },
    { title: '列37', field: 'col37', width: 400 },
    { title: '列38', field: 'col38', width: 800 },
    { title: '列39', field: 'col39', width: 360 },
    { title: '列40', field: 'col40', width: 420 },
    { title: '列41', field: 'col41', width: 100 },
    { title: '列42', field: 'col42', width: 120 },
    { title: '列43', field: 'col43', width: 280 },
    { title: '列44', field: 'col44', width: 170 },
    { title: '列45', field: 'col45', width: 370 },
    { title: '列46', field: 'col46', width: 420 },
    { title: '列47', field: 'col47', width: 170 },
    { title: '列48', field: 'col48', width: 400 },
    { title: '列49', field: 'col49', width: 220 },
    { title: '列50', field: 'col50', width: 170 },
    { title: '列51', field: 'col51', width: 160 },
    { title: '列52', field: 'col52', width: 500 },
    { title: '列53', field: 'col53', width: 280 },
    { title: '列54', field: 'col54', width: 170 },
    { title: '列55', field: 'col55', width: 370 },
    { title: '列56', field: 'col56', width: 120 },
    { title: '列57', field: 'col57', width: 170 },
    { title: '列58', field: 'col58', width: 400 },
    { title: '列59', field: 'col59', width: 220 },
    { title: '列60', field: 'col60', width: 650 },
    { title: '列61', field: 'col61', width: 600 },
    { title: '列62', field: 'col62', width: 100 },
    { title: '列63', field: 'col63', width: 490 },
    { title: '列64', field: 'col64', width: 100 },
    { title: '列65', field: 'col65', width: 150 },
    { title: '列66', field: 'col66', width: 800 },
    { title: '列67', field: 'col67', width: 400 },
    { title: '列68', field: 'col68', width: 800 },
    { title: '列69', field: 'col69', width: 360 },
    { title: '列70', field: 'col70', width: 650 },
    { title: '列71', field: 'col71', width: 600 },
    { title: '列72', field: 'col72', width: 100 },
    { title: '列73', field: 'col73', width: 490 },
    { title: '列74', field: 'col74', width: 100 },
    { title: '列75', field: 'col75', width: 150 },
    { title: '列76', field: 'col76', width: 800 },
    { title: '列77', field: 'col77', width: 400 },
    { title: '列78', field: 'col78', width: 800 },
    { title: '列79', field: 'col79', width: 360 },
    { title: '列80', field: 'col80', width: 650 },
    { title: '列81', field: 'col81', width: 600 },
    { title: '列82', field: 'col82', width: 100 },
    { title: '列83', field: 'col83', width: 490 },
    { title: '列84', field: 'col84', width: 100 },
    { title: '列85', field: 'col85', width: 150 },
    { title: '列86', field: 'col86', width: 800 },
    { title: '列87', field: 'col87', width: 400 },
    { title: '列88', field: 'col88', width: 800 },
    { title: '列89', field: 'col89', width: 360 },
    { title: '列90', field: 'col90', width: 650 },
    { title: '列91', field: 'col91', width: 600 },
    { title: '列92', field: 'col92', width: 100 },
    { title: '列93', field: 'col93', width: 490 },
    { title: '列94', field: 'col94', width: 100 },
    { title: '列95', field: 'col95', width: 150 },
    { title: '列96', field: 'col96', width: 800 },
    { title: '列97', field: 'col97', width: 400 },
    { title: '列98', field: 'col98', width: 70, fixed: 'right' },
    { title: '列99', field: 'imgList1', width: 120, fixed: 'right', cellRender: imgList1CellRender },
    { title: '列100', field: 'flag1', width: 100, fixed: 'right', cellRender: flag1CellRender }
  ],
  data: []
})
// 模拟行数据
const loadData = (rowSize) => {
  const dataList = []
  for (let i = 0; i < rowSize; i++) {
    const item = {
      id: 10000 + i,
      imgUrl: i % 3 === 0 ? 'https://vxeui.com/resource/img/546.gif' : 'https://vxeui.com/resource/img/673.gif',
      imgList1: i % 4 === 0
        ? [
            { name: 'fj577.jpg', url: 'https://vxeui.com/resource/img/fj577.jpg' }
          ]
        : [
            { name: 'fj573.jpeg', url: 'https://vxeui.com/resource/img/fj573.jpeg' },
            { name: 'fj562.png', url: 'https://vxeui.com/resource/img/fj562.png' }
          ],
      flag1: i % 5 === 0
    }
    for (let j = 0; j < 120; j++) {
      item[`col${j}`] = `值_${i}_${j}`
    }
    dataList.push(item)
  }
  gridOptions.loading = true
  setTimeout(() => {
    const startTime = Date.now()
    gridOptions.data = dataList
    gridOptions.loading = false
    nextTick(() => {
      VxeUI.modal.message({
        content: `加载时间 ${Date.now() - startTime} 毫秒`,
        status: 'success'
      })
    })
  }, 100)
}
loadData(200)

</script>

以上复杂度还不是很高,当渲染复杂度更大是,鼠标滚轮的速度快于渲染速度,这是就会出现渲染期空白。
可以通过设置参数 scroll-y.mode = ‘wheel’ 解决,虚拟滚动操作过快渲染期空白问题

// ...
scrollY: {
  enabled: true,
  gt: 0,
  mode: 'wheel'
},
// ...

在这里插入图片描述

滚动操作是非常流畅的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2218646.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI论文写作:如何轻松实现高原创度大揭秘

随着人工智能技术的迅猛进步&#xff0c;AI论文写作工具在学术界开始崭露头角&#xff0c;作为一种辅助手段。这些工具不仅能高效地生成论文的初步版本或部分章节&#xff0c;而且其产出的内容往往展现出高度的创新性。本文将探讨AI论文写作工具为何能产出如此高原创度的内容&a…

欢迎观看在线直播|李航和张志华等嘉宾解读:人工智能和诺贝尔奖相遇,是偶然还是必然?

人工智能是新一轮产业革命的核心技术&#xff0c;受到了各个国家和不同领域人士的高度重视。不仅如此&#xff0c;它还为基础科学的研究创造出了新的研究范式。诺贝尔奖是科学界最著名的奖项之一&#xff0c;可谓是万众瞩目。2024年的诺贝尔物理奖和化学奖均授予了具有人工智能…

mysql的各种存储引擎

文章目录 前言1. InnoDB特点 2. MyISAM特点innodb与myisam引擎之间的区别 3. MEMORY特点 4. ARCHIVE特点 5. NDBCluster特点 6. FEDERATED特点 7. CSV特点 总结 前言 MySQL 支持多种存储引擎&#xff0c;每种引擎都有其独特的功能和适用场景。存储引擎是指数据库管理系统用来存…

Apache Seatunnel Zeta引擎-启动脚本分析

Apache SeaTunnel Zeta引擎的集群模式启动的第一步是执行bin/seatunnel-cluster.sh脚本&#xff0c;所以先来学习下这个脚本。 脚本执行流程分析 脚本简要注释 #!/bin/bash # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license a…

【Tinymce】富文本编辑器在vue项目中的使用;引入付费格式刷,上传视频、图片

引言 富文本编辑器有很多&#xff0c;对比了一下&#xff0c;还是决定用tinymce&#xff08;号称宇宙最强&#xff09;&#xff0c;基础的插件确实好用&#xff0c;但是一些更好用的插件&#xff0c;比如格式刷等都是高级版&#xff08;付费&#xff09;&#xff0c;当然也有人…

day-69 构成整天的下标对数目 II

思路 根据题意&#xff0c;每个元素可以重复使用&#xff0c;所以只需统计对24取余后值值相同的个数&#xff0c;如当前数字对24取余后是3&#xff0c;那么只需知道取余后为21的元素个数即可知道当前元素可与&#xff0c;多少个元素构成整天的下标的数目 解题过程 从左往右遍历…

数据结构编程实践20讲(Python版)—20并查集

本文目录 20 并查集&#xff08;Union-Find Set&#xff09;S1 说明并查集的定义并查集基本操作并查集优化并查集特点应用领域 S2 示例S3 问题1&#xff1a;朋友圈问题S4 问题2&#xff1a;网络连接恢复问题S5 问题3&#xff1a;随机生成迷宫 往期链接 01 数组02 链表03 栈04 …

023_Layout_and_Containers_in_Matlab界面布局与容器

容器 基于uifigure进行的图形用户界面设计&#xff0c;可以分为以下几种容器类型&#xff1a; 图窗&#xff1a;uifigure布局&#xff1a;uigridlayout面板&#xff1a;uipanel标签页&#xff1a;uitabgroup、uitab 这几个对象除uifigure外相互可以形成嵌套的关系&#xff0…

【新人系列】Python 入门(二):Python IDE 介绍

✍ 个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4dd; 专栏地址&#xff1a;https://blog.csdn.net/newin2020/category_12801353.html &#x1f4e3; 专栏定位&#xff1a;为 0 基础刚入门 Python 的小伙伴提供详细的讲解&#xff0c;也欢迎大佬们…

leetcode.204.计数质数

#中等#枚举 给定整数 n &#xff0c;返回 所有小于非负整数 n 的质数的数量 。 埃氏筛 枚举没有考虑到数与数的关联性&#xff0c;因此难以再继续优化时间复杂度。接下来我们介绍一个常见的算法&#xff0c;该算法由希腊数学家厄拉多塞&#xff08;Eratosthenes&#xff09;提…

Python爬虫:自动化获取商品评论数据

为什么选择Python爬虫API 高效的数据处理&#xff1a;Python的数据处理能力&#xff0c;结合Pandas等库&#xff0c;可以轻松处理和分析大量的评论数据。丰富的库支持&#xff1a;Python拥有丰富的库&#xff0c;如requests用于发送HTTP请求&#xff0c;BeautifulSoup用于解析…

初识MySQL · 数据库

目录 前言&#xff1a; 数据库 简单使用 存储引擎 前言&#xff1a; 本文也是MySQL的第一篇文章了&#xff0c;新的知识点已经出现&#xff0c;怎么能够停止不前&#xff0c;穿越时空……(迪迦奥特曼乱入哈哈哈)。 言归正传&#xff0c;我们在本文的目标有&#xff1a; …

工厂生成中关于WiFi的一些问题

一 背景: 主要做高通和MTK,工厂生成中通过使用adb wifi,因为这样生产效率高并且避免了新机器有划痕,但是也经常碰到adb wifi无法连接的问题,那么是什么原因导致呢? 二 案例 测试步骤: 使用adb wifi连接手机测试工厂case adb usb adb tcpip 5555 adb connect DU…

高效监控系统:Nightingale本地化部署与远程访问指南

文章目录 前言1. Linux 部署Nightingale2. 本地访问测试3. Linux 安装cpolar4. 配置Nightingale公网访问地址5. 公网远程访问Nightingale管理界面6. 固定Nightingale公网地址 前言 本文主要介绍如何在本地Linux系统部署 Nightingale 夜莺监控并结合cpolar内网穿透工具实现远程…

Android组件化、模块化、Catalogs

前言 下载代码-----》码云下载 下载代码-----》github下载 本篇是Android最新的依赖架构设计&#xff0c;gradle版本要8.0以上&#xff0c;代码实现基于8.5.1。好多年开发过程中&#xff0c;我们碰到config.gradle&#xff0c;buildSrc&#xff0c;composing builds等依赖编译…

新款任天堂switch游戏机方案,支持4K60HZ投屏方案,显示器,手柄方案

据传任天堂将推出新的一代的switch掌机&#xff0c;而新款掌机将支持4K60HZ投屏 都2402年了再做1080P确实有点不太象话了 4K60HZ相较于1080P能够提升很多游戏体验&#xff0c;这时不管是HDMI显示器或者是VR眼睛清晰度都会让人舒服很多。 不过新一代的任天堂似乎也在PD协议上…

用作曲的手法写旋律 什么是动机 ​动机扩大 单音重复 移八度

【你怎么还不会写旋律&#xff01;&#xff01;&#xff01;猴子都听的懂的旋律教程来了&#xff01;两分钟让你快速上手&#xff01;】 你怎么还不会写旋律&#xff01;&#xff01;&#xff01;猴子都听的懂的旋律教程来了&#xff01;两分钟让你快速上手&#xff01;_哔哩哔…

同济子豪兄--图的基本表示【斯坦福CS224W图机器学习】

无向图&#xff08;Undirected Graph&#xff09;&#xff1a; 在无向图中&#xff0c;边没有方向&#xff0c;即如果顶点A和顶点B之间有一条边&#xff0c;那么这条边既表示A到B的关系&#xff0c;也表示B到A的关系。换句话说&#xff0c;边是双向的。无向图的边通常用一条线段…

WPF基础权限系统

一.开发环境 VisualStudio 2022NET SDK 8.0Prism 版本 8.1.97Sqlite 二. 功能介绍 WPF 基础权限系统&#xff0c;是一个支持前后端分离设计的 客户端(C/S)项目&#xff0c;该示例项目前端xaml使用UI库 &#xff0c;Material Design Themes UI 来构建用户界面&#xff0c;确保…

Ubuntu如何显示pcl版本

终端输入&#xff1a; apt-cache show libpcl-dev可以看到&#xff0c;Ubuntu20.04&#xff0c;下载的pcl&#xff0c;应该都是1.10版本的