乐趣区

关于javascript:纯前端翻页跨页级联勾选的实现

需要形容

实现对数据库表和表字段的勾选,数据库表蕴含了表字段,后端一次性返回所有表的数据。前端须要自行对表做翻页解决。当用户勾选完须要的表和字段后,再把勾选后的数据发送给后端。

需要拆分

  1. 前端翻页性能
  2. 跨页级联勾选性能

实现成果

具体实现

前端翻页性能

须要实现前端翻页的局部是数据库表,进入页面后,默认主动向后端获取一次 搜寻后的表数据 searchTableList,获取到之后,计算当前页显示的表数据,计算公式为 curTableList = searchTableList.slice((page - 1) * size, page * size)pagesize 保留在 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);
},

跨页级联勾选性能

剖析用户可进行的勾选操作的勾选框:

  1. 全副表勾选框,共有未选、局部先和全选有三种状态,未选和局部选状态点击可勾选全副表,全选状态点击可勾销勾选全副表;
  2. 以后页表勾选框,共有未选、局部选和全选有三种状态,未选和局部选状态点击可勾选当前页全副表,全选状态点击可勾销勾选当前页全副表;
  3. 单个表勾选框,共有未选、局部选和全选有三种状态,未选和局部选状态点击可勾选表中的全副字段,全选状态点击可勾销勾选表中的全副字段;
  4. 全副字段勾选框,共有未选、局部选和全选有三种状态,未选和局部选状态点击可勾选表中的全副字段,全选状态点击可勾销勾选表中的全副字段;
  5. 单个字段勾选框,共有未选和已选有两种状态,未选状态点击可勾选表中的该字段,已选状态点击可勾销勾选表中的该字段;

全副表数据 allTableList,该数据结构如下:

// 全副表
allTableList: [
    // 每个表
    {
        "tableName": "table-name", // 表名
        // 表中的全副字段
        "fieldList": [
            // 每个字段
            {"fieldName": "field-name", // 字段名},
        ],
    },
]

依据下面的信息剖析,为了实现勾选状态的联动,最好的方法是把所有的已勾选项放在一个变量中保留,该变量保留了选中的表和字段,而后通过计算方法确定每个勾选框的状态。该勾选状态变量的构造如下:

// 选中的表和字段
checkedTableAndField: {
    // 选中的表名
    "table-name": ["field-name", // 表中选中的字段],
}

有了 checkedTableAndField 变量,所有的勾选框状态就都能够通过它来计算失去了。上面列出所有勾选框状态的计算方法:

  1. 全副表勾选框,全选状态 = 全副表状态都全选,局部选状态 = 自身非全选状态且有任一表是局部选或全选状态,未选状态 = 自身非全选且自身非局部选。转换为代码如下:
// 全副表是否全选
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));
},
  1. 以后页表勾选框,全选状态 = 以后页表状态都全选,局部选状态 = 自身非全选状态且有任一以后页表是局部选或全选状态,未选状态 = 自身非全选且自身非局部选。转换为代码如下:
// 当前页的表是否全选
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));
},
  1. 单个表勾选框,全选状态 = 表中的全副字段状态都勾选,局部选状态 = 自身非全选状态且表中有任一字段勾选,未选状态 = 自身非全选且自身非局部选。转换为代码如下:
// 单个表是否全选
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;
},
  1. 全副字段勾选框,全选状态 = 全副字段状态都勾选,局部选状态 = 自身非全选状态且有任一字段勾选,未选状态 = 自身非全选且自身非局部选。转换为代码如下:
// 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;}
  1. 单个字段勾选框,勾选状态 = 自身是勾选,未选状态 = 自身非勾选。转换为代码如下:
// 单个字段是否勾选
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);
},

总结

以上就实现了纯前端翻页 + 跨页级联勾选成果。纯前端翻页是把先把搜寻数据保留在本地变量中,而后通过数组的切片性能,依据当前页数和大小进行切片,再把后果保留到当前页中。跨页级联抉择是先把所有数据保留在本地变量中,再剖析如何确定各个勾选框状态,最初通过一个保留了已勾选的表和字段状态的变量进行状态更新。这其中的重点便是了解如何构建和保护这样一个变量。

另外,纯前端翻页是目标是为了可能实现跨页级联勾选性能,因为只有后端返回了所有的数据给咱们,咱们能力计算出全副抉择勾选框的状态。数据量过大的状况下,后端即便返回了所有数据给咱们,浏览器也无奈进行大量数据的保留和计算。这种状况下,须要采取另外的计划。

退出移动版