当前位置:   article > 正文

element select默认选中_element-ui checkbox 组件的树形联动

handlecheckchange

前言

示例版本为 Element-ui 2.13.0 + Vue 2.6.11

最近想弄 Element-ui checkbox 的多级联动,网上相关的例子大多数为二级联动,自己研究了一下,弄了一个树形菜单的多级联动,常用于角色管理等业务。(仅供参考,未考虑性能问题)

数据模型

  1. [
  2. {
  3. "menu": {
  4. "id":14,
  5. "menuName":"测试管理',
  6. "parentId":0
  7. } ,
  8. "menuOptionsList":[
  9. {
  10. "id":46,
  11. "optionsName":"列表",
  12. "checked":false
  13. },
  14. {
  15. "id":47,
  16. "optionsName":"新增",
  17. "checked":false
  18. }
  19. ],
  20. "children":[],
  21. "checked":false
  22. }
  23. ]

这里展示的最顶级的数据结构,下级数据只需要在 children 中添加即可。需要注意的是 checked 属性,本身数据库表中没有这个数据,需要后台建立一个 VO 映射实体将 checked 字段添加进去,默认值为 false.

逻辑处理

html 使用 el-table + el-chekbox 展示:

292c2bcb4abb6dcd98992ffa9c771ef9.png
  1. <el-table
  2. :data="menuList"
  3. border
  4. fit
  5. size="mini"
  6. highlight-current-row
  7. row-key="menu.id"
  8. :default-expand-all="true"
  9. :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
  10. >
  11. <el-table-column label="菜单名称" width="180">
  12. <template slot-scope="scope">
  13. <el-checkbox
  14. v-model="scope.row.checked"
  15. :indeterminate="scope.row.indeterminate"
  16. @change="handleCheckAllChange(scope.row, $event)">
  17. {{ scope.row.menu.menuName }}
  18. </el-checkbox>
  19. </template>
  20. </el-table-column>
  21. <el-table-column label="功能选项">
  22. <template v-if="scope.row.children.length === 0" slot-scope="scope">
  23. <el-checkbox
  24. v-for="options in scope.row.menuOptionsList"
  25. :key="options.id"
  26. v-model="options.checked"
  27. :label="options.optionsName"
  28. @change="handleCheckChange(scope.row)"
  29. />
  30. </template>
  31. </el-table-column>
  32. </el-table>

核心方法 handleCheckAllChangehandleCheckChange 这两个方法,handleCheckAllChange菜单选项 列按钮被点击的事件,handleCheckChange选项列表 列被点击的事件。

handleCheckAllChange(菜单列改变事件)

  1. handleCheckAllChange(val, checked) {
  2. // 有下级去处理下级
  3. if (val.children.length > 0) {
  4. // 递归设置子级选中状态
  5. this.findChildren(val.children, checked)
  6. } else {
  7. // 无下级处理本级
  8. val.menuOptionsList.forEach(options => { options.checked = checked })
  9. }
  10. // 处理上级
  11. if (val.menu.parentId !== 0) {
  12. 递归设置上级选中状态
  13. this.findParent(this.menuList, val.menu.parentId)
  14. }
  15. // 设置全选的未全部选中的状态
  16. val.indeterminate = false
  17. }

根据数据中 children 的长度来判断是否存在下级,如果存在就执行递归方法 findChildren 将子类的 checked 属性设置为 true,不存在处理本级的 checked 属性即可。需要注意的是 parentId 等于 0 证明当前菜单父级为顶级菜单,不需要再向上寻找。以此为判断依据来进行父级菜单的判断条件。 如果 parentId 不等于 0 说明当前全选的菜单存在父级,需要将父级的选项框进行状态设置。

handleCheckChange(选项列改变事件)

  1. handleCheckChange(val) {
  2. const length = val.menuOptionsList.length
  3. let checkedLength = 0
  4. val.menuOptionsList.forEach(options => {
  5. if (options.checked) {
  6. checkedLength++
  7. }
  8. })
  9. val.checked = checkedLength === length
  10. val.indeterminate = checkedLength > 0 && checkedLength < length
  11. // 处理上级
  12. if (val.menu.parentId !== 0) {
  13. this.findParent(this.menuList, val.menu.parentId)
  14. }
  15. }

这个方法对应着 选项列表 列选中的状态,需要对 菜单名称 列的全选状态进行控制。首先通过变量 length 获取到当前数据行选项列表的数量,遍历选项数组根据 checked 的状态获取到已选中的选项数量。val.checked 代表当前列是否全选,val.indeterminate 代表当前列是否有选项被选中。但是这只是处理了当前行的状态,当前行可能是某一菜单的子集,所以需要由下向上的去寻找菜单的父级并设置选中状态。这里同样用到了上面方法中的 findParent 函数。

findChildren(递归查询子集)

  1. findChildren(list, checked) {
  2. list.forEach(children => {
  3. children.checked = checked
  4. children.indeterminate = false
  5. children.menuOptionsList.forEach(options => {
  6. options.checked = checked
  7. if (children.children.length > 0) {
  8. this.findChildren(children.children, checked)
  9. }
  10. })
  11. })
  12. }

findParent(递归查询父集)

  1. findParent(list, parentId) {
  2. list.forEach(result => {
  3. let parentCheckedLength = 0
  4. let parentIndeterminateLength = 0
  5. if (result.menu.id === parentId) {
  6. result.children.forEach(children => {
  7. if (children.indeterminate) {
  8. parentIndeterminateLength++
  9. } else if (children.checked) {
  10. parentCheckedLength++
  11. }
  12. })
  13. result.checked = parentCheckedLength === result.children.length
  14. result.indeterminate = (parentIndeterminateLength > 0 || parentCheckedLength > 0) && parentCheckedLength < result.children.length
  15. if (result.menu.parentId !== 0) {
  16. this.findParent(this.menuList, result.menu.parentId)
  17. }
  18. } else if (result.children.length > 0) {
  19. this.findParent(result.children, parentId)
  20. }
  21. })
  22. }

完整示例

由于源码篇幅过长,暂时将源码放到 GitHub 了,希望可以帮助到你。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/107301
推荐阅读
相关标签
  

闽ICP备14008679号