openks / learn-vue

自定义组件文档
https://openks.github.io/learn-vue
0 stars 0 forks source link

20180515_一对多数据关联关系状态管理及实现方案 #109

Open openks opened 6 years ago

openks commented 6 years ago

需求A:需要做一个一对多的关联关系状态管理界面

左侧是一个列表右侧是一个带分页可勾选列表 实现方案:前端维护所有关联数据

  1. 进入页面后先获取右侧列表数据tableData2
  2. 左侧点击时获取与这条记录相关的右侧列表的所有页的ids组成的数组, 拼成id 字符串后复制两份分别保存在selectedIds1(服务端返回ids)及selectedIds2(用于用户交互)
  3. 遍历tableData2获取selectedIds2tableData2里的index
  4. 根据tableData2index值回填右侧列表 用户操作会修改selectedIds2的值,前端需同时处理跨页数据,
    点击下一页获取该页数据后,根据selectedIds2回填数据(需要在nextTick里回填,同一个macrotask里回填不成功)
    // 用户点击操作
    selectHander (selection, row) {
    // 如果已选变未选则移除,
    // 如果未选变已选则加入
    let tmp2 
    let id = row.id
    if (this.selectedIds2.length > 0) {
        let tmp = this.selectedIds2.split(',')
        tmp2= new Set(tmp)
    }
    if (tmp2.has(id)) {
        tmp2.delete(id)
    } else {
        tmp2.add(id)
    }
    this.selectedIds2 = [...tmp2].join(',')
    // console.log('rowrowrowrow', this.selectedIds2)
    },
    // 根据ids设置表格数据回填
    setRowSelectedByIds (ids) {
    let idsStr = ids
    let tb2 = this.tableData2
    let rowsIndexs = this.getRowsIndexByIds(idsStr)
    let rows = rowsIndexs.map(index => {
        return tb2[index]
    })
    // console.log('rowsIndexs', rowsIndexs, rows, tb2)
    // 先清空所有选中 再设置该选项
    this.$refs.Table2.clearSelection()
    this.toggleRowSelectionHander(rows)
    },
    // 根据idstr获取table2的index值
    getRowsIndexByIds (idstr) {
    let idArr = idstr.split(',')
    let datas = this.tableData2
    let arrReturn = []
    idArr.forEach(id => {
        let t = datas.findIndex(data => {
            return data.id === id
        })
        // 如果选中的数据 不在当前页则t为undefined
        if (t !== -1) {
            arrReturn.push(t)
        }
    })
    // console.log('合适数组index', arrReturn)
    return arrReturn
    },

    需求A1:由于多的一方可能会配置很多需要添加批量选择功能

    即 需要添加右侧列表的全选功能

    selectAllHander(selection){
    // 这里selection是该页的所有选中数据
    // 选中id数组连接已选id数组即selectedIds2转换后的数组
    // 通过set去重后再转换为数组在变为id字符串即可
    let ids2 = this.selectedIds2;
    let arr = selection.map(ele=>ele.id).concat(ids2.split(","))
    this.selectedIds2 = [...new Set(arr)].join(",")
    }

    需求A2:多的一方添加查询条件

    这个不影响只需要在查询的时候添加相应的查询条件即可

总结

方案一已经实现,但方案不是很好 缺点:

  1. 每一个数据的改变都需要与已选项进行对比并处理(判断移除该项还是添加该项)
  2. 如果已选项比较多时服务端返回的将会是一个很大的数组而大部分数据是无用的
  3. 已选项比较多时id组成的字符串会比较大 优点:
  4. 用户只需点击一次保存,所有页数据的操作都会得到保留

方案二: 点击左侧返回所有右侧已选数据用于翻页后数据回填 保存时只处理当页数据的关联关系 缺点:

  1. 每一页用户都需要点击保存按钮否则数据会造成数据丢失
  2. 如果已选项比较多时服务端返回的将会是一个很大的数组而大部分数据是无用的 优点:
  3. 保存时不需要给全部数据,只需要给当页数据不会造成页面因勾选项过多造成页面过于卡顿

方案三: 点击左侧仅返回右侧当前页已选数据。 上下页及跳页时需根据查询条件及左侧已选获取该页数据及该页回填数据。 点击左侧时需同时把右侧所有查询条件一并传过去,用于服务端处理。 服务端只需要根据查询条件获取右侧要显示的当页数据, 及根据左侧已选项获取右侧已选项id与右侧要显示页数据列表id的交集即可 此方案最优,且只需一个接口