赞
踩
在el-element的标签里的tableData数据过多时,会导致表格页面操作卡顿。为解决这一问题,有以下解决方法:
分页加载: 将大量数据进行分页,并且只在用户需要时加载当前页的数据,可以减轻页面的数据负担。可以使用像 Element UI 提供的分页组件来实现分页加载功能。
虚拟滚动: 对于大量数据的列表展示,可以考虑使用虚拟滚动技术,只渲染当前可见区域的数据,而不是直接渲染所有数据。Element UI 的 Table 组件也支持虚拟滚动,可以通过相应的配置开启虚拟滚动功能。可参考虚拟滚动其它博主的文章
数据筛选和搜索: 提供数据筛选和搜索功能,让用户可以根据条件快速定位到需要的数据,减少不必要的数据展示。
服务端优化: 如果数据来源于服务端,可以在服务端对数据进行分页、压缩等处理,以减少前端页面加载的数据量。
组件优化: 检查页面中其他组件的性能表现,确保没有其他组件或代码导致页面性能下降。
前端性能优化: 考虑对前端代码进行性能优化,比如减少不必要的重复渲染、减少对大数据量的循环操作等。
表格分页+搜索+勾选
数据结构:
created () {
// 模拟生成大量数据
for (let i = 0; i < 1000; i++) {
this.tableData.push({
date: '2023-11-28',
name: '用户' + i,
age: i + '岁',
ID: i
// 其他字段
});
}
},
data:
tableData: [], // 原始数据
currentPage: 1, // 当前页码
pageSize: 10, // 每页显示的数量
searchText: ‘’, // 搜索的文本
filteredData: [], // 搜索后的数据
multipleSelection: [],//已勾选的项
首先,在computed中,使用displayData计算属性来根据当前页码和每页数量筛选出要显示的数据。在el-table标签中绑定displayData:<el-table :data="displayData"></el-table>
通过computed属性,我们可以定义根据响应式数据计算的属性,并在模板中使用。Vue会自动追踪依赖关系,当依赖的响应式数据发生变化时,computed属性会重新计算其值。
computed: {
// 根据当前页码和每页数量计算显示的数据
displayData () {
const startIndex = (this.currentPage - 1) * this.pageSize;
const endIndex = startIndex + this.pageSize;
return this.tableData.slice(startIndex, endIndex);
},
},
其次,在methods中,handleSizeChange方法用于处理改变每页显示数量的事件,handleCurrentChange方法用于处理改变当前页码的事件。
// 改变每页显示的数量时触发
handleSizeChange(newSize) {
this.pageSize = newSize;
this.currentPage = 1; // 重置当前页码为第一页
},
// 改变当前页码时触发
handleCurrentChange(newPage) {
this.currentPage = newPage;
},
最后,在mounted中,我们假设通过某种方式获取了原始数据,并将其赋值给tableData数组,若是调用接口,则在调用接口将获取的数据赋值给tableData数组即可。这里示例是用的json数据。
data () { return { tableData: jsondata,//方法一:使用示例数据进行演示,将json数据赋值给tableData数组 }; }, mounted() { // 方法二:实际情况下可以通过接口请求或其他方式获取数据 // 假设tableData是从后端获取的原始数据 this.searchFun(); }, methods: { searchFun(){ //......调用接口 .then((res) => {this.tableData = res.obj;//将数据赋值给tableData}) .catch((err) => {console.log("err",err);}) }, }
这样,当用户改变每页显示数量或当前页码时,表格会自动根据新的参数重新渲染显示数据,同时Element UI的分页组件也会更新页码和显示的数据数量
1、在data中,添加了filteredData用于存储搜索后的数据,searchText用于保存搜索的文本。
searchText: '', // 搜索的文本
filteredData: [], // 搜索后的数据
2、在computed中,修改了displayData计算属性,使用filteredData进行分页显示。
computed: {
displayData () {
// 根据当前页码和每页数量计算显示的数据
const startIndex = (this.currentPage - 1) * this.pageSize;
const endIndex = startIndex + this.pageSize;
return this.filteredData.slice(startIndex, endIndex);
},
},
3、在mounted钩子中,初始化了tableData和filteredData,并将它们设置为示例数据。你可以根据实际情况从后端获取数据。
4、在methods中,添加了searchTextFun 方法来根据搜索文本过滤数据,并重置当前页码为第一页。若是在调用接口方法获取数据后调用searchTextFun即可。这里用的是name字段,可视情况改变:item.name.includes(this.searchText)
.filter()方法直达站
mounted () {
this.filteredData = this.tableData;
this.searchTextFun();
},
methods: {
// 根据搜索文本过滤数据
searchTextFun () {
this.filteredData = this.tableData.filter(item =>
item.name.includes(this.searchText)
);//过滤数据
this.currentPage = 1; // 重置当前页码为第一页
},
}
5、在watch中,监听searchText的变化,并在变化时执行搜索操作。
watch: {
searchText () {
// 监听搜索文本变化,执行搜索操作
this.searchTextFun();
},
}
这样,当用户输入搜索文本并提交时,表格会根据搜索结果显示相应的数据,并自动根据新的参数重新渲染分页组件。
el-table自带的select和select-all事件,并通过ref调用对应表格元素的toggleRowSelection方法实现勾选项,以下是官网api的说明:
arguments 对象是一个类数组对象,它包含了函数参数的值以及一些有用的属性和方法。当函数被调用时,arguments 对象会自动被创建,并且可以在函数内部使用。
这里的@select="tableHandleSelect"
方法被调用时传递了两个参数(list和item),则 arguments 对象的第一个元素就是第一个参数(list),第二个元素就是第二个参数(item),依此类推。我们可以通过下标来访问 arguments 对象中的各个参数,也可以直接使用参数list和item。
并且利用list.includes(item)
来判断当前用户是点击勾选复选框还是取消复选框,若是勾选,则返回为true;否则为false。
最后使用了箭头函数和filter()方法,通过筛选条件item.ID !== arguments[1].ID
,创建一个新的数组存储所有已勾选的数组,其中不包含要删除(取消复选框)的对象。
// 表格的select方法
tableHandleSelect (list, item) {
console.log("list", list);
console.log("item", item);
console.log("arguments", arguments);
if (list.includes(item)) {//勾选
console.log('勾选arguments[0]', arguments[0]);
this.multipleFun(arguments[0]);// 调用勾选复选框的方法
} else {//取消勾选
this.multipleSelection = this.multipleSelection.filter(item => item.ID !== arguments[1].ID);
}
console.log("已勾选数组multipleSelection:", this.multipleSelection);
},
一下代码为补充代码,勾选复选框的逻辑和去重逻辑
// 勾选复选框的方法 multipleFun (val) { if (this.multipleSelection.length) { var templist = []; for (var i in this.multipleSelection) { templist.push(this.multipleSelection[i]); if (val.length) { for (var j in val) { templist.push(val[j]); } } } this.multipleSelection = []; this.multipleSelection = JSON.parse(JSON.stringify(templist)) } else { for (var z in val) { this.multipleSelection.push(val[z]); } } this.multipleSelection = this.removeDuplicatesV2(this.multipleSelection);//去重 }, // 去重方法 removeDuplicatesV2 (array) { const res = new Map() return array.filter((item) => !res.has(item.ID) && res.set(item.ID, 1)) },
这里需要考虑两个方向,一个是当前页表格的点击全勾选,一个是当前页表格的点击全部取消勾选。突破点就是根据参数selection,根据输出可以发现点击全选时它返回的是一个与pageSize相同长度的数组,反之则是个空数组。
通过@select-all="allHandleSelect"
方法把对应页数中所有数据全部勾选,譬如,当前为第一页10条数据,点击表头的全选时,第一页的全部十条都被勾选中;再次点击取消全选时,将已勾选数据与当前页所有数据ID进行对比返回一个不相同ID的新数组对象。
// 全选
allHandleSelect (selection) {
console.log("selection", selection);
if (selection.length) {//点击全选
this.multipleFun(selection);
} else {//点击取消全选 移除multipleSelection数组中与当前页数据相同ID的元素
console.log("displayData", this.displayData);//当前页的所有数据
this.multipleSelection = this.multipleSelection.filter(item => !this.displayData.some(sel => sel.ID === item.ID));
}
console.log("全选的multipleSelection", this.multipleSelection);
},
<template> <div class="textbox-class"> <div class="topbox-class"> <el-input placeholder="搜索姓名" prefix-icon="el-icon-search" v-model="searchText" class="mleft-class searchinput-class"> </el-input> <div class="mleft-class"> 您已勾选{{multipleSelection.length}}项 </div> </div> <div class="mainbox-class"> <el-table :data="displayData" stripe border :header-cell-style="{background:'rgb(113 167 228)',color:'white'}" @select="tableHandleSelect" @select-all="allHandleSelect" ref="tableRef" highlight-current-row height="520" style="width: 50%"> <el-table-column type="selection" fixed="left" width="50"></el-table-column> <el-table-column prop="date" label="日期"> </el-table-column> <el-table-column prop="name" label="姓名"> </el-table-column> <el-table-column prop="age" label="年龄"> </el-table-column> </el-table> </div> <div class="botbox-class"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[10,20,30,40,50]" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.length"></el-pagination> </div> </div> </template> <script> export default { data () { return { tableData: [], // 这里存放大量数据的数组 filteredData: [], // 搜索后的数据 currentPage: 1, // 当前页码 pageSize: 10, // 每页显示的数量 searchText: '', // 搜索的文本 multipleSelection: [],//已勾选的项 }; }, created () { // 模拟生成大量数据 for (let i = 0; i < 1000; i++) { this.tableData.push({ date: '2023-11-28', name: '用户' + i, age: i + '岁', ID: i // 其他字段 }); } }, computed: { displayData () { // 根据当前页码和每页数量计算显示的数据 const startIndex = (this.currentPage - 1) * this.pageSize; const endIndex = startIndex + this.pageSize; return this.filteredData.slice(startIndex, endIndex); }, }, mounted () { this.filteredData = this.tableData; this.searchTextFun(); }, methods: { // 改变每页显示的数量时触发 handleSizeChange (newSize) { this.pageSize = newSize; this.currentPage = 1; // 重置当前页码为第一页 this.$nextTick(() => { this.toggleSelection(); }); }, // 改变当前页码时触发 handleCurrentChange (newPage) { this.currentPage = newPage; this.$nextTick(() => { this.toggleSelection(); }); }, // 根据搜索文本过滤数据 searchTextFun () { this.filteredData = this.tableData.filter(item => item.name.includes(this.searchText) ); this.currentPage = 1; // 重置当前页码为第一页 this.toggleSelection(); }, // 表格的select方法 tableHandleSelect (list, item) { console.log("list", list); console.log("item", item); console.log("arguments", arguments); var val = arguments[0];//勾选的数据,array if (list.includes(item)) {//勾选时做的事 console.log('勾选arguments[0]', arguments[0]); this.multipleFun(arguments[0]); } else { //取消勾选时做的事,arguments[1]是当前取消勾选的项 this.multipleSelection = this.multipleSelection.filter(item => item.ID !== arguments[1].ID); } console.log("已勾选数组multipleSelection:", this.multipleSelection); }, // 全选 allHandleSelect (selection) { console.log("selection", selection); if (selection.length) {//点击全选 this.multipleFun(selection); } else {//点击取消全选 移除multipleSelection数组中与当前页数据相同ID的元素 console.log("displayData", this.displayData);//当前页的所有数据 this.multipleSelection = this.multipleSelection.filter(item => !this.displayData.some(sel => sel.ID === item.ID)); } console.log("全选的multipleSelection", this.multipleSelection); }, // 勾选复选框的方法 multipleFun (val) { if (this.multipleSelection.length) { var templist = []; for (var i in this.multipleSelection) { templist.push(this.multipleSelection[i]); if (val.length) { for (var j in val) { templist.push(val[j]); } } } this.multipleSelection = []; this.multipleSelection = JSON.parse(JSON.stringify(templist)) } else { for (var z in val) { this.multipleSelection.push(val[z]); } } this.multipleSelection = this.removeDuplicatesV2(this.multipleSelection); }, // 去重方法 removeDuplicatesV2 (array) { const res = new Map() return array.filter((item) => !res.has(item.ID) && res.set(item.ID, 1)) }, // 默认勾上已选的项 toggleSelection () { if (this.multipleSelection.length == 0) { return; } this.$nextTick(() => { this.multipleSelection.forEach(item => { for (var i of this.displayData) { if (item.ID == i.ID) { this.$refs.tableRef.toggleRowSelection(i, true) } } }) }) }, }, watch: { searchText () { // 监听搜索文本变化,执行搜索操作 this.searchTextFun(); }, } }; </script> <style scoped> .textbox-class { width: 100%; height: 100%; } .topbox-class { height: 5%; display: flex; align-items: center; margin-left: 0.5rem; } .mainbox-class { height: 55%; } .botbox-class { height: 3%; } .searchinput-class { width: 20%; } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。