【项目复盘-Vue2】element实现el-tree和el-table联动,el-table多页全选功能,el-tree全部节点禁选

 【项目复盘-Vue2】element实现el-tree和el-table联动,el-table多页全选功能,el-tree全部节点禁选_第1张图片

 需要实现的需求:

1.el-table多选框选中,左边对应的树状多选框勾选

2.el-table多页全选功能:在当前页点击多页全选按钮,当前树状节点对应的el-table全部数据全部选中,并且可以回显实现增删改功能

比较啰嗦,可以直接点目录跳到指定部分内容

左边el-tree功能实现分析

1.开启多选框: show-checkbox="true",参考官网api

2.禁用:每一层的树状结点的数据都要有disabled属性,并且disabled="true"

3.支持节点搜索:参考官网节点过滤部分:Element - The world's most popular Vue UI framework

4.节点名称过长显示...并且出现tooltip:在el-tree使用作用域插槽slot-scope添加el-tooltip改写el-tree原来节点

参考:el-tree文字显示不全的解决办法 / 张生荣  

参考: elementui中el-tree实现复选框全部禁用_咖啡壶子的博客-CSDN博客

----------------------------------------------------------------------------分割线 ------------------------------------------

实现

template部分代码

         // 部门上方搜索框
          

        // 树状控件
          
            // 节点过长悬浮el-tooltip显示全名
            
              
                {{ node.label }}
              
            
          

1.开启多选:实现看template的代码

2.节点多选框禁用实现方法:

// 在生命周期中调用
created() {
    this.getTreeData()
}

methods: {
    // 树状结构全部禁选
    disabledFn (treeData) {
        // 采用遍历+递归设置disabled:true
      treeData.forEach(item => {
        this.$set(item, 'disabled', true)
        if (item.children) {
          this.disabledFn(item.children)
        }
      })
    },

    // 请求el-tree数据的方法
    getTreeData () {
        // xxxx 发送请求
        xxapi().then(res => {
            this.treeData = res.data
        }).then(() => {
            // 调用禁选方法 $nextTick是为了防止节点未完全渲染完毕
            this.$nextTick(() => {
                this.disabledFn(this.treeData)
            })
        })
    }
}   


3.节点搜索实现方法:

 watch: {
      filterText(val) {
        this.$refs.tree.filter(val);
      }
 },


 methods: {
      filterNode(value, data) {
        if (!value) return true;
        return data.label.indexOf(value) !== -1;
      }
 },

4.节点名称过长显示... css代码

.span-ellipsis {
  font-size: 14px;
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

使用el-tooltip看上方template代码

右边el-table分析

1.表格多选: 添加一个type="selection"的列 

2.序号列: 参考自定义索引 Element - The world's most popular Vue UI framework

3.保存单行勾选的数据(选中/取消勾选):

选中-如果保存数据的数组里面没有这行数据就添加

取消勾选-如果数组里面有这行数据就删除

4.表头全选(全选/全不选):

全选-保存整页数据

全不选-删除整页数据

5.多页全选

该节点对应的表格所有页码的数据全都加入保存数据的数组里面

点击其他页码或者切换节点回到原页面勾选的数据都能回显,并且增删操作能够与保存数据的数组同步(响应式)

--------------------------------------------------------------------------------------分割线-------------------------------

实现:

template部分


// 开启表格的多选
    
// 序号列
    
// 其他列赋值
    
    

1.表格多选:看template部分代码

2.序号列实现相关方法:

methods: {
   // 生成表格序号列
    indexMethod (index) {
      return index + (this.pageIndex - 1) * this.pageSize + 1
    }
}

 3.保存勾选的数据

这里的实操与分析时候的实现逻辑是有出入的

坑一:存在多页数据的情况下,不能直接使用elm的所有select方法的参数作为勾选数据

因为在type="selection"这个列里添加reserve-selection属性后,el-table会记住你勾选的行,保存在el-table组件里面的selection属性里。也就是说,添加了reserve-selection属性后,通过this.$refs['multipleTable'].selection获取到的就是此时el-table所有选中的数据,并且这个属性是只读的!如果表格数据重新渲染,el-table会通过匹配当前表格每一行的数据和selection属性保存的数组数据,如果匹配到一样的就会自动回显勾选状态。(后面也因为这个摔在坑里久久爬不起……= = )

如果只需要单页表格的勾选,应该可以直接使用elm事件的参数(参考官网api)

【项目复盘-Vue2】element实现el-tree和el-table联动,el-table多页全选功能,el-tree全部节点禁选_第2张图片

但是存在多页数据的情况下,不能直接使用elm的所有select方法的参数作为勾选数据(血泪教训),因为重新渲染表格this.$refs['multipleTable'].selection的数据会丢失(这也是多页全选回显实现的坑之一)

坑二:勾选表头全选(select-all)会触发select-change事件

因为所有功能已经做好了,不想写测试,感兴趣的可以自己写试试(代码能跑起来就别动它了对吧T...T)

这里爬坑爬了很久,直到看到这篇文章才解决(感谢up!!)el-table多选回显使用toggleRowSelection被动触发selection-change事件导致选择数据重复问题_正在前行的小码农的博客-CSDN博客

这里很重要!一定要多看几遍!!!

坑三:回显勾选遍历对比一定要用el-table的data数据,不然无法出现选中状态

 elm提供的toggleRowSelection一定要作用于el-table的表格数据,在我的代码里就是userList(看template部分)

坑四:回显遍历时使用toggleRowSelection会出现死循环,要用setiTimeout才能解决

【项目复盘-Vue2】element实现el-tree和el-table联动,el-table多页全选功能,el-tree全部节点禁选_第3张图片

 祭出我的经典之图

 前面讲过this.$refs['muitlple'].selection是只读属性,当用toggleRowSelection改变勾选状态与this.$refs['muitlple'].selection的数据发生冲突时,elm会自动将你的toggleRowSelection改掉。

-------------------------------------------------------踩坑记录完毕----------------------------------------------------

踩完了坑,现在说怎么实现:

【项目复盘-Vue2】element实现el-tree和el-table联动,el-table多页全选功能,el-tree全部节点禁选_第4张图片

1.添加了reserve-selection属性一定要加row-key属性,最好以id为row-key,接受string/function

2.设立一个空数组selectList,实现最终数据的crud

2.因为选中elm会记录,所以用户手动触发select/select-all事件的时候只需要关注删除逻辑即可

select事件:

    // 取消单行勾选
    selectSingleRow (selection, row) {
      console.log('i am select event 单行勾选/单行取消勾选', selection, row)
      if (!selection.includes(row)) {
        this.rowSelectFlag = true
        let idx = this.selectList.findIndex(item => item.id === row.id)
        if (idx !== -1) {
          this.selectList.splice(idx, 1)
        }
      } else {
        this.rowSelectFlag = true // 禁止开关,为true就可以不触发select-change事件
        this.selectList.push(row)
      }
    }

 select-change事件

    // 保存单行勾选
    handleSelectionChange (val) {
      console.log(val, 'val') // 这里的val是这个表格所有勾选中的rows
      if (val.length >= this.pageSize || val.length === 0) { // 说明曾经有全选状态 / 取消全选状态
        this.rowSelectFlag = true
      }
      if (this.rowSelectFlag) return
      this.selectList = val
    },

 select-all事件

通过this.$refs['multipleTable'].store.states.isAllSelected判断此时是否全选

    // 取消表头全选
    selectAllRows (selection) {
      console.log(this.$refs['multipleTable'].store.states.isAllSelected, 'selectAllRows是否全选')
      clearTimeout(this.allSelectTimer)
      this.allSelectTimer = setTimeout(() => {
        if (this.$refs['multipleTable'].store.states.isAllSelected) { // 全选状态
          this.selectList.push(...this.userList) // 如果是全选就把表格数据全部添加进去
        } else { // 取消全选状态
          this.duplicateArr()
          this.userList.forEach(row => {
            let matchedIdx = this.selectList.findIndex(item => item.id === row.id)
            if (matchedIdx !== -1) {
              this.selectList.splice(matchedIdx, 1)
            }
          })
        }
      }, 0)
    },

3.现在最终保存的数据selectList能够做到视图和数据保持一致了,但是回显是有问题的,需要写一个回显函数在每次请求数据之后$nextTick调用showCheck

回显函数:(因为我将数据保存在sessionStorage里面,所以我会从session里取已经勾选到的数据),回显函数一定要用setTimeout才不会出现死循环

    // 表格所选行回显
    showCheck () {
      clearInterval(this.showCheckTimer)
      this.showCheckTimer = setTimeout(() => {
        this.rowSelectFlag = true
        this.oldSelection = JSON.parse(window.sessionStorage.getItem('selectedUser'))
        this.selectList = this.oldSelection
        // console.log(this.oldSelection, 'sesson里面的')
        this.userList.forEach(row => {
          const matchedIndex = this.oldSelection.findIndex(item => item.id === row.id)
          this.$refs['multipleTable'].toggleRowSelection(row, matchedIndex !== -1)
        })
        this.rowSelectFlag = false
      }, 0)
    },

 注意:此时this.$refs['multipleTable'].selection的数据还是这一页勾选的!!!视图和数据是存在割裂的,但是翻页或者切换部门调用showCheck会将selectList的数据重新添加进el-table的selection属性中,翻页回显打印一下即可看到this.$refs['multipleTable'].selection是会不断添加的,但是不翻页elm只会保存当前页面的selection

解决了以上问题:多页全选也能顺势而为

4.多页全选:

实现逻辑就是请求el-tree节点对应的全部数据添加进selectList里面,因为根据分页进行请求的话页面表格的分页也会拉大,所以push了数据之后要修改分页重新请求

    // 多页全选
    selectAllPage () {
      // this.queryParams.pageSize = 10000
      let params = this.queryParams
      params.pageSize = 10000
      examPaperApi.getPaperSetting(params).then(response => {
        this.selectList.push(...response.response.list)
      }).then(() => {
        this.queryParams.pageSize = 10
        this.handleNodeClick(this.chooseNode)
      })
    },

 5.最后selectList这个数组会出现很多重复的rows,传送数据的时候记得去重(建议采用reduce去重)

参考: reduce()方法详解之数组对象去重_reduce数组对象去重_可可爱爱的你吖的博客-CSDN博客

el-tree和el-table联动分析

功能需求:

1.点击左边el-tree节点,右边表格更新对应节点的数据

2.右边表格勾选了属于左边节点的数据,左边对应节点多选框为选中状态

实现:将上面去重了之后的selectList提取每个row对象的el-tree节点id进行匹配,再用el-tree的setCheckedKeys设置勾选

    // 选中右边表格用户联动左边部门勾选
    deptCheckedKeys () {
      let deptIds = this.selectList.map(sUser => sUser.deptIds)
      deptIds = deptIds.flatMap(item => item)
      let sDeptIds = deptIds.map(dept => dept.deptId)
      let uniqueDeptId = (sDeptIds) => [...new Set(sDeptIds)]
      if (uniqueDeptId(sDeptIds).length !== 0) {
        this.$nextTick(() => {
          this.$refs.tree.setCheckedKeys(uniqueDeptId(sDeptIds))
        })
        return uniqueDeptId(sDeptIds)
      } else {
        this.$nextTick(() => {
          this.$refs.tree.setCheckedKeys([])
        })
        return []
      }
    }

你可能感兴趣的:(项目复盘分析类,vue,归错类,vue.js,elementui,前端)