Element Plus 跟踪表格数据总数,包括查询、筛选等操作

news2024/9/21 0:29:39

前言

Element Plus的表格组件提供了筛选功能

前端项目中,如果表格使用的是后端分页,使用表格插件及分页器插件就可以了。这种情况下,前端的表格筛选被后端的分页条件查询取代了

另一种情况:不分页,直接查询所有数据,在前端做查询、筛选、排序

第一种情况下,数据统计由后端直接返回。这里,讨论的是第二种情况

一、需求

想要实现的是在上述第二种情况下,在进行前端筛选、重新获取数据等改变表格内数据总数的操作后,获取该总数。

然而,无法从 ElTable 组件绑定的数据、公开的属性/方法中直接获知

二、解决方案

示例基于 element-plus@2.2.9, vue@3.2.37,使用 vue组合式API实现

文末有 vue3 两种代码风格的完整代码

1. 基本示例

下面是个人员表格,可筛选性别、省份

<script setup>
import { ref, computed, onMounted } from "vue";
import { ElButton, ElTable, ElTableColumn } from "element-plus";

const provinces = ["北京", "上海", "广东"];
const tableData = ref([]);
const columns = [
  { label: "No", prop: "no", width: 80 },
  { label: "Name", prop: "name", width: 100 },
  { label: "Age", prop: "age", width: 60 },
  {
    label: "Gender",
    prop: "gender",
    width: 100,
    filterable: true,
    filters: [
      { text: "male", value: "male" },
      { text: "female", value: "female" },
    ],
  },
  {
    label: "Province",
    prop: "province",
    width: 140,
    filterable: true,
    filters: [
      { text: "北京", value: "北京" },
      { text: "上海", value: "上海" },
      { text: "广东", value: "广东" },
    ],
  },
  { label: "Tel", prop: "tel", width: 140 },
];

const tableEl = ref();

onMounted(() => {
  queryHandler();
});

// 获取列表数据
function getTableData(amount = 200) {
  return new Promise((resolve, reject) => {
    resolve(
      Array.from({ length: amount }).map((_, idx) => ({
        no: "No." + (idx + 1),
        name: Math.floor(Math.random() * 900000 + 100000).toString(16),
        age: Math.ceil(Math.random() * 40 + 20),
        gender: Math.random() > 0.5 ? "male" : "female",
        province: provinces[Math.floor(Math.random() * 3)],
        tel: "13311112222",
      }))
    );
  });
}
async function queryHandler() {
  tableEl.value?.clearFilter();
  const amount = Math.floor(Math.random() * 900) + 100;
  tableData.value = await getTableData(amount);
}

function filterHandler(value, row, column) {
  const property = column["property"];
  return row[property] === value;
}
</script>

<template>
  <el-table ref="tableEl" :data="tableData" max-height="500">
    <template v-for="col in columns" :key="col.prop">
      <el-table-column
        v-if="col.filterable"
        :prop="col.prop"
        :label="col.label"
        :width="col.width"
        :filters="col.filters"
        :filter-method="filterHandler"
      ></el-table-column>
      <el-table-column
        v-else
        :prop="col.prop"
        :label="col.label"
        :width="col.width"
      ></el-table-column>
    </template>
  </el-table>
  <el-button @click="queryHandler">重新请求列表数据</el-button>
</template>

从表格绑定数据 tableData 中无法获知筛选后的表格数据总量,查阅 Element Plus 官方文档,该组件也没有提供相应接口,那就只能想办法通过某种方案间接实现了

2. 方案

  • 方案一:直接将筛选方法作用于 tableData,手动计算筛选后的表格数据总数

这种方案需要监听表格的 filter-change 事件,然后过滤

由于 filter-change 事件返回的当前更改的筛选条件,存在多个筛选时,需存储过滤条件

总结一下:

> 给表项绑定 column-key 属性;创建存储筛选条件的对象
> 监听表格的 filter-change 事件,更新筛选条件,计算筛选后的表格数据总数
> 表格数据变更时,清空筛选条件

上述第二步,手动计算筛选如果过于复杂,也可以考虑在DOM层面上,在表格渲染完毕后,直接查询条数(<tr>)。

  • 方案二:监听表格组件内部数据

虽然官方未提供直接的属性与方法,但表格组件内部肯定知道满足筛选条件的数据有哪些,问题在于它是否被暴露出来

通过打印表格对象,发现store中找到了相关数据,ElTable 组件内部的状态存储信息:

在这里插入图片描述
更完美的是,它是响应式变量,意味着可以直接监听

上例中,我们只需要中添加一个计算变量即可:

import { ref, computed, onMounted } from "vue";

const tableEl = ref();
const total = computed(
  () => tableEl.value?.store?.states?.data?.value?.length ?? 0
);

注意:若使用的是vue选项式API实现,需等待表格组件挂载后,再添加计算变量

三、总结

第一种方案监听筛选事件,再在监听处理事件中手动筛选数据、计算总数,较为繁琐,不太建议使用

方案二依赖于 ElTable 组件内部的状态存储信息,非官网提供的属性/方法,随着版本的更替,指不定什么时候就成潜在的 “Breaking Change” 了。建议核实后锁定项目的 element-plus 的版本

若官方后续提供相应属性/方法,再替换。

四、完整代码

Demo - 基于vue选项式API

Demo - 基于vue组合式API:

<script setup>
import { ref, computed, onMounted } from "vue";
import { ElButton, ElTable, ElTableColumn } from "element-plus";

const provinces = ["北京", "上海", "广东"];
const tableData = ref([]);
const columns = [
  { label: "No", prop: "no", width: 80 },
  { label: "Name", prop: "name", width: 100 },
  { label: "Age", prop: "age", width: 60 },
  {
    label: "Gender",
    prop: "gender",
    width: 100,
    filterable: true,
    filters: [
      { text: "male", value: "male" },
      { text: "female", value: "female" },
    ],
  },
  {
    label: "Province",
    prop: "province",
    width: 140,
    filterable: true,
    filters: [
      { text: "北京", value: "北京" },
      { text: "上海", value: "上海" },
      { text: "广东", value: "广东" },
    ],
  },
  { label: "Tel", prop: "tel", width: 140 },
];

const tableEl = ref();
const total = computed(
  () => tableEl.value?.store?.states?.data?.value?.length ?? 0
);

onMounted(() => {
  queryHandler();
});

// 获取列表数据
function getTableData(amount = 200) {
  return new Promise((resolve, reject) => {
    resolve(
      Array.from({ length: amount }).map((_, idx) => ({
        no: "No." + (idx + 1),
        name: Math.floor(Math.random() * 900000 + 100000).toString(16),
        age: Math.ceil(Math.random() * 40 + 20),
        gender: Math.random() > 0.5 ? "male" : "female",
        province: provinces[Math.floor(Math.random() * 3)],
        tel: "13311112222",
      }))
    );
  });
}
async function queryHandler() {
  tableEl.value?.clearFilter();
  const amount = Math.floor(Math.random() * 900) + 100;
  tableData.value = await getTableData(amount);
}

function filterHandler(value, row, column) {
  const property = column["property"];
  return row[property] === value;
}
</script>

<template>
  <h3>TableData length: {{ tableData.length }}</h3>
  <h3>Total entries: {{ total }}</h3>
  <el-table ref="tableEl" :data="tableData" max-height="500">
    <template v-for="col in columns" :key="col.prop">
      <el-table-column
        v-if="col.filterable"
        :prop="col.prop"
        :label="col.label"
        :width="col.width"
        :filters="col.filters"
        :filter-method="filterHandler"
      ></el-table-column>
      <el-table-column
        v-else
        :prop="col.prop"
        :label="col.label"
        :width="col.width"
      ></el-table-column>
    </template>
  </el-table>
  <el-button @click="queryHandler">重新请求列表数据</el-button>
</template>

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

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

相关文章

Win7快速部署weblogic 12c

0x00 前言 需要一个漏洞中等数量的版本。 0x01 安装环境 版本操作系统Windows 7 64bitJDKjdk-8u101-windows-x64weblogic12.2.1.3 0x02 下载地址 JDK 下载地址 https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html jdk 1.8版本&#xff0c;文…

华为机试题:HJ16 购物单(python)

文章目录知识点详解1、input()&#xff1a;获取控制台&#xff08;任意形式&#xff09;的输入。输出均为字符串类型。2、print() &#xff1a;打印输出。3、strip()&#xff1a;删除字符串&#xff08;开头 / 结尾&#xff09;指定字符&#xff08;默认空格&#xff09;或字符…

两小时上手ActiveMQ

一、消息中间件概述 1.1 消息中间件产生的背景 在客户端与服务器进行通讯时.客户端调用后&#xff0c;必须等待服务对象完成处理返回结果才能继续执行。 客户与服务器对象的生命周期紧密耦合,客户进程和服务对象进程都都必须正常运行;如果由于服务对象崩溃或者网络故障导致用…

ceres学习笔记(四)

前言&#xff1a; 学习了pose_graph_2d部分&#xff0c;因为先学习了3维的pose_graph_3d部分&#xff0c;所以这个就比较容易。简单来说就是se2和se3的区别。整个的运行逻辑和3维部分的pose_graph_3d部分是一样的&#xff0c;概括为&#xff1a; 1.设置好两个type&#xff0c…

7、CenOS6安装Nginx

Nginx的安装与启动 什么是Nginx Nginx 是一款高性能的 http 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。由俄罗斯的程序设计师伊戈尔西索夫&#xff08;Igor Sysoev&#xff09;所开发&#xff0c;官方测试 nginx 能够支支撑 5 万并发链接…

《早安隆回》的铁粉,深圳80后男子不计成本,收购袁树雄签名照

谁也没有想到&#xff0c;五十多岁并且离异多年的袁树雄&#xff0c;靠着一首《早安隆回》&#xff0c;一夜之间红遍大江南北。如今《早安隆回》这首歌曲&#xff0c;已经拥有了三百万流量&#xff0c;有人说袁树雄下辈子都吃喝不愁&#xff0c;他的前妻该后悔了。 《早安隆回》…

ue4c++日记4(控制pawn类的运动|创建游戏模式|)

目录 代码速查 调用数学公式 获取位置/设置位置 绑定玩家输入按键&#xff0c;UE4传值给函数进行处理 约束获得的值再输出 创建对象 对象绑定到xxx上 设定默认玩家 实例&#xff1a;sin函数实现往复运动 实例&#xff1a;删除c类 1.删掉cpp和.h文件 2.删编译好的文件B…

缓存Caffeine之W-TinyLFU淘汰测录

我们常见的缓存是基于内存的缓存&#xff0c;但是单机的内存是有限的&#xff0c;不能让缓存数据撑爆内存&#xff0c;所有需要缓存淘汰机制。https://mp.csdn.net/editor/html/115872837 中大概说明了LRU的缓存淘汰机制&#xff0c;以及基于LRU的著名实现guava cache。除了LRU…

Python学习笔记——类(面向对象)

Python中使用类&#xff08;class〕来实现面向对象编程。Python中的类, 具有面向对象编程的所有基本特征&#xff1a;允许多继承、派生类可以重写它父类的任何方法、方法可以调用父类中同名的方法, 对象可以包含任意数量和类型的数据成员。创建类Python中, 使用class语句来创建…

Python 第7章 文件与数据格式化 笔记1

编码&#xff1a;print(云.encode(utf8))print(b\xe4\xba\x91.decode(utf8))要注意代码的编码方式。7.1文件概述windows中一个文件的完标识&#xff1a;D:\Downloads\新建文本文档.txt依次是路径&#xff0c;文件名主干&#xff0c;拓展名。没有包含除了文本字符以外的其他数据…

【JavaEE初阶】第四节.多线程基础篇 Thread类的使用、线程的几个重要操作和状态

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、Thread类的常见构造方法 二、Thread 的几个常见属性 三、和线程相关的几个重要的操作 3.1 启动线程 - start() 3.2 中断线程 3.3 等待线程 - join() …

JDK 8新特性之基本发展史

目录 一&#xff1a;Java SE的发展历史 二&#xff1a;Open JDK来源 三&#xff1a;Open JDK 和 Oracle JDK的关系 四&#xff1a;Open JDK 官网介绍 小结 &#xff1a; 一&#xff1a;Java SE的发展历史 Sun公司在1991年成立了一个称为绿色计划( Green Project )的项目&a…

Ubuntu22.04 美化

一&#xff1a;安装软件 sudo apt install gnome-tweaks chrome-gnome-shell sudo apt install gtk2-engines-murrine gtk2-engines-pixbuf sudo apt install sassc optipng inkscape libcanberra-gtk-module libglib2.0-dev libxml2-utils 二&#xff1a;安装GNOME扩展插件…

Windows 卸载 Visual Studio Code、MinGW-w64、CMake

文章目录1.卸载 Visual Studio Code1.1 在控制面板中找到 Visual Studio Code 将其卸载1.2 删除之前安装过的插件1.3 删除用户信息和缓存信息2.卸载 MinGW-w642.1 删除之前解压出来的文件夹2.2 删除之前配置过的环境变量3.卸载 CMake3.1 删除之前解压出来的文件夹3.2 删除之前配…

无 Hadoop 环境部署 Kylin4

1相比于 Kylin 3.x&#xff0c;Kylin 4.0 实现了全新 spark 构建引擎和 parquet 存储&#xff0c;使 kylin 不依赖 hadoop 环境部署成为可能。无Hadoop环境也降低了运维成本&#xff0c;减少了系统资源占用。 以下操作基于centos7.6 单机版本 部署版本信息如下 JDK 1.8Hive …

【Javascript】面向对象编程,this,原型与原型链,类与实例,class,实现Map,stack,Queue ,Set

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录对象中的方法/thisthis使用bind函数原型原型链类与实例classclass语法补充Map实现Map实现stack实…

【国产GD32芯片解析中科微北斗+GPS模块经纬度数据详细教程-附完整代码工程】

国产GD32芯片解析中科微北斗GPS模块经纬度数据详细教程-附完整代码工程简介准备工作PC端需要用到的工具代码下载地址GD32F103C8T6最小系统板代码实现GD32串口引脚定义如下&#xff1a;串口的初始化串口0初始化代码&#xff1a;串口1初始化代码串口的输入串口0的输入代码如下&am…

非标准包 game.rgss3a 的打开方法 | 2023 年实测

写在前面&#xff1a;最近在玩 RPG 游戏&#xff0c;想拆一个 Game.rgss3a 包&#xff0c;在网上找了很久的拆包方法&#xff0c;感觉写的比较凌乱&#xff0c;我来给大家整理一下吧。不过我本人的技术能力也很差&#xff0c;不确定说的是不是对的&#xff0c;就当是给大家提供…

中国智造助推跨境电商企业迈向全球市场

现今&#xff0c;跨境电商行业发展的如火如荼&#xff0c;中国智造也在不断助推跨境电商企业迈向全球市场。业内人员在新常态下的思想也有了一些改变&#xff0c;现在的跨境电商都是“平台物流”&#xff0c;在物流环节&#xff0c;也需要我们的专业团队去进行整合&#xff0c;…

GD32F450寄存器和库函数

GD32F4xx用户手册 GD32F450xx数据手册 GD32F3x0固件库使用指南 一、寄存器介绍 1. 存储器映射表 GD32是一个32位的单片机&#xff0c;它的地址范围为2的32次方&#xff0c;也就是4GB的地址空间。 为了降低不同客户在相同应用时的软件复杂度&#xff0c;存储映射是按Corte…