共计 5158 个字符,预计需要花费 13 分钟才能阅读完成。
需要形容
实现对数据库表和表字段的勾选,数据库表蕴含了表字段,后端一次性返回所有表的数据。前端须要自行对表做翻页解决。当用户勾选完须要的表和字段后,再把勾选后的数据发送给后端。
需要拆分
- 前端翻页性能
- 跨页级联勾选性能
实现成果
具体实现
前端翻页性能
须要实现前端翻页的局部是数据库表,进入页面后,默认主动向后端获取一次 搜寻后的表数据 searchTableList
,获取到之后,计算当前页显示的表数据,计算公式为 curTableList = searchTableList.slice((page - 1) * size, page * size)
,page
,size
保留在 url
参数中。如果用户点击翻页,则从新计算当前页显示的表数据。如果用户搜寻表,则重置页数为 1
后,获取 searchTableList
,并从新计算当前页显示的表数据。
流程图
要害代码
// 获取以后页表数据
getCurTableList() {
// 不发申请,依据 searchTableList 获取数据。模仿翻页
let page = Number(this.$route.query.page || 1);
let size = Number(this.$route.query.size || 10);
let total = this.searchTableList.length;
let maxPage = Math.ceil(total / size);
page = page > maxPage ? maxPage : page;
this.tablePageData = {page, size, total};
this.curTableList = this.searchTableList.slice((page - 1) * size, page * size);
},
跨页级联勾选性能
剖析用户可进行的勾选操作的勾选框:
- 全副表勾选框,共有未选、局部先和全选有三种状态,未选和局部选状态点击可勾选全副表,全选状态点击可勾销勾选全副表;
- 以后页表勾选框,共有未选、局部选和全选有三种状态,未选和局部选状态点击可勾选当前页全副表,全选状态点击可勾销勾选当前页全副表;
- 单个表勾选框,共有未选、局部选和全选有三种状态,未选和局部选状态点击可勾选表中的全副字段,全选状态点击可勾销勾选表中的全副字段;
- 全副字段勾选框,共有未选、局部选和全选有三种状态,未选和局部选状态点击可勾选表中的全副字段,全选状态点击可勾销勾选表中的全副字段;
- 单个字段勾选框,共有未选和已选有两种状态,未选状态点击可勾选表中的该字段,已选状态点击可勾销勾选表中的该字段;
全副表数据 allTableList,该数据结构如下:
// 全副表
allTableList: [
// 每个表
{
"tableName": "table-name", // 表名
// 表中的全副字段
"fieldList": [
// 每个字段
{"fieldName": "field-name", // 字段名},
],
},
]
依据下面的信息剖析,为了实现勾选状态的联动,最好的方法是把所有的已勾选项放在一个变量中保留,该变量保留了选中的表和字段,而后通过计算方法确定每个勾选框的状态。该勾选状态变量的构造如下:
// 选中的表和字段
checkedTableAndField: {
// 选中的表名
"table-name": ["field-name", // 表中选中的字段],
}
有了 checkedTableAndField
变量,所有的勾选框状态就都能够通过它来计算失去了。上面列出所有勾选框状态的计算方法:
- 全副表勾选框,全选状态 = 全副表状态都全选,局部选状态 = 自身非全选状态且有任一表是局部选或全选状态,未选状态 = 自身非全选且自身非局部选。转换为代码如下:
// 全副表是否全选
isTableAllChecked() {return this.allTableList.length && this.allTableList.every(tableObj => this.isPerTableAllChecked(tableObj));
},
// 全副表是否局部选
isTablePartChecked() {return !this.isTableAllChecked && this.allTableList.some(tableObj => this.isPerTablePartChecked(tableObj) || this.isPerTableAllChecked(tableObj));
},
- 以后页表勾选框,全选状态 = 以后页表状态都全选,局部选状态 = 自身非全选状态且有任一以后页表是局部选或全选状态,未选状态 = 自身非全选且自身非局部选。转换为代码如下:
// 当前页的表是否全选
isCurTableAllChecked() {return this.curTableList.length && this.curTableList.every(tableObj => this.isPerTableAllChecked(tableObj));
},
// 当前页的表是否局部选
isCurTablePartChecked() {return !this.isCurTableAllChecked && this.curTableList.some(tableObj => this.isPerTablePartChecked(tableObj) || this.isPerTableAllChecked(tableObj));
},
- 单个表勾选框,全选状态 = 表中的全副字段状态都勾选,局部选状态 = 自身非全选状态且表中有任一字段勾选,未选状态 = 自身非全选且自身非局部选。转换为代码如下:
// 单个表是否全选
isPerTableAllChecked(tableObj) {let checkedFieldArr = vm.checkedTableAndField[tableObj.tableName];
return checkedFieldArr && checkedFieldArr.length === tableObj.fieldList.length;
},
// 单个表是否局部选
isPerTablePartChecked(tableObj) {let checkedFieldArr = vm.checkedTableAndField[tableObj.tableName];
return !vm.isPerTableAllChecked(tableObj) && checkedFieldArr && checkedFieldArr.length;
},
- 全副字段勾选框,全选状态 = 全副字段状态都勾选,局部选状态 = 自身非全选状态且有任一字段勾选,未选状态 = 自身非全选且自身非局部选。转换为代码如下:
// this.allFieldList 是以后选中的表的所有字段,这里省略该变量局部代码
// 以后已选中的字段的标识汇合
curCheckedFieldArr() {return this.checkedTableAndField[this.curTableName] || [];},
// 全副字段是否全选
isFieldAllChecked() {return this.allFieldList.length && this.allFieldList.length === this.curCheckedFieldArr.length;},
// 全副字段是否局部选
isFieldPartChecked() {return !this.isFieldAllChecked && this.curCheckedFieldArr.length;}
- 单个字段勾选框,勾选状态 = 自身是勾选,未选状态 = 自身非勾选。转换为代码如下:
// 单个字段是否勾选
isFieldChecked(fieldName) {return curCheckedFieldArr.includes(fieldName)
}
以上逐渐剖析了各个勾选框的状态如何确定,根本围绕着 checkedTableAndField
变量进行,那么当咱们更新 checkedTableAndField
的数据,所有的勾选框状态都会随着它更新了。这里贴出来更新 checkedTableAndField
数据的局部代码(详情参考具体我的项目实现):
// 点击 抉择全副表
checkAllTable() {
let vm = this;
let checkedTableAndField = {};
if (!vm.isTableAllChecked) {
vm.allTableList.forEach(tableObj => {checkedTableAndField[tableObj.tableName] = tableObj.fieldList.map(item => item.sensTypeMain.fieldName);
});
} else {
vm.allTableList.forEach(tableObj => {checkedTableAndField[tableObj.tableName] = [];});
}
vm.checkedTableAndField = checkedTableAndField;
},
// 点击 抉择当前页的表
checkCurTable() {
let vm = this;
let checkedTableAndField = {};
if (!vm.isCurTableAllChecked) {
vm.curTableList.forEach(tableObj => {checkedTableAndField[tableObj.tableName] = tableObj.fieldList.map(item => item.sensTypeMain.fieldName);
});
} else {
vm.curTableList.forEach(tableObj => {checkedTableAndField[tableObj.tableName] = [];});
}
vm.checkedTableAndField = checkedTableAndField;
},
// 点击 抉择单个表
checkPerTable(tableObj) {
let vm = this;
let checkedFieldArr = !vm.isPerTableAllChecked(tableObj) ? tableObj.fieldList.map(item => item.sensTypeMain.fieldName) : [];
this.$set(this.checkedTableAndField, tableObj.tableName, checkedFieldArr);
},
// 点击 抉择以后显示的全副字段
checkCurAllField() {
let vm = this;
let checkedFieldArr = !vm.isFieldAllChecked ? vm.allFieldList.map(item => item.sensTypeMain.fieldName) : [];
this.$set(this.checkedTableAndField, this.curTableName, checkedFieldArr);
},
// 点击 抉择字段
checkField(fieldName) {let checkedFieldArr = this.checkedTableAndField[this.curTableName];
if (checkedFieldArr) {let position = checkedFieldArr.indexOf(fieldName);
position > -1 ? checkedFieldArr.splice(position, 1) : checkedFieldArr.push(fieldName);
} else {checkedFieldArr = [fieldName];
}
this.$set(this.checkedTableAndField, this.curTableName, checkedFieldArr);
},
总结
以上就实现了纯前端翻页 + 跨页级联勾选成果。纯前端翻页是把先把搜寻数据保留在本地变量中,而后通过数组的切片性能,依据当前页数和大小进行切片,再把后果保留到当前页中。跨页级联抉择是先把所有数据保留在本地变量中,再剖析如何确定各个勾选框状态,最初通过一个保留了已勾选的表和字段状态的变量进行状态更新。这其中的重点便是了解如何构建和保护这样一个变量。
另外,纯前端翻页是目标是为了可能实现跨页级联勾选性能,因为只有后端返回了所有的数据给咱们,咱们能力计算出全副抉择勾选框的状态。数据量过大的状况下,后端即便返回了所有数据给咱们,浏览器也无奈进行大量数据的保留和计算。这种状况下,须要采取另外的计划。