实现效果

注意tree原生是,如果子集只选中了一个,父级是方块样式选中,而不是对号方式选中。最终获取的checkedKeys列表中是不会包含方块选中的父级id的,但是这对后端数据授权处理是不友好的。

那么怎么然传到后端的checkedKeys包含上面所说的父级id呢。我想出了两个方案:

1.就是tree是关联状态,即:checkStrictly="false"(tree默认就是这个可以不写),有关联时候我们可以通过check方法获得关联的方块选中的父级有哪些,这个数组在info.halfCheckedKeys字段里面。

不过要注意的是,后端是需要哪些父级选中了,你传给后端的时候可以是checkedKeys合并info.halfCheckedKeys放到一个数组里面给后端的,但是问题在于下一次获取的时候数据里面包含了父级id,默认tree的效果就是,包含id时候就会全部选中,所以原来是一个子集被选中,但是根据保存数据在此复现就是该子集同胞级和父级都被选中了。跟你初始设置大相径庭,问题就出在没有把哪些不满足全部选中的父级id剔除,如果菜单是多级的,可想这是一个复杂的逻辑啊。那么我这里想了第一个办法就是,传给后端时候选checkedKeys和info.halfCheckedKeys分开传,满足了后端筛选菜单的需求,缺点就是数据表设计不规范。前端就可以下次获取数据的时候只利用全部选中的这个字段进行复现,避免了js编写筛出未全部选中的父级id的工作。

2.就是tree是未关联状态,即:checkStrictly="true",未关联就是父级选中时候子集未响应,同样的子集选中父级也不会有什么反应。这个方法我已经使用方法实现了,思路就是利用check方法里面的e.node.eventKey(当前选择的id或者取消的id)去找他的子孙id和他的父爷id,获取到集合整理到this.checkedKeys用于tree显示。

 页面部分:

 <a-tree
          checkable
          selectable
          :checkedKeys="checkedKeys"
          :tree-data="menuAll"
          :checkStrictly="true"
          :replaceFields="{ children: 'children', title: 'name', key: 'id' }"
          @check="onCheck"
        />

 js部分:

onCheck(checkedKeys, e) {
      this.checkedKeys = checkedKeys;
      let list = backFather(
        e.node.eventKey,
        this.menuAll,
        "children",
        "parentId"
      );
      let children = selectAllChild(e.node.eventKey, this.menuAll);
      if (e.checked) {
        // 选中添加:1.如果有父级,将各层父级都勾选;
        this.checkedKeys.checked.push(...list);
         //去除重复id
        this.checkedKeys.checked = [...new Set(this.checkedKeys.checked)];
        // 2.如果有子集,将所有子集都勾选
        this.checkedKeys.checked.push(...children);
      } else {
        // 1.去掉相关父级数字
        this.checkedKeys.checked = this.checkedKeys.checked.filter(
          (x) => !list.some((item) => x == item)
        );
        // 2.去掉子集数据
        this.checkedKeys.checked = this.checkedKeys.checked.filter(
          (x) => !children.some((item) => x == item)
        );
      }
    },
//找到他的关联父级放到一个数组里
export function backFather(id, tree, childName, parentId, end = 0) {
  var list = [id];
  var that = this;
  function backarr(childId, arr) {
    arr.forEach((item) => {
      if (item.id == childId) {
        // 找到指定的id了,进入寻找父级id
        if (item[parentId] == end) {
          // 到第一级了
          // list.unshift(0);
        } else {
          // 进入循环查找
          list.unshift(item[parentId]);
          backarr(item[parentId], tree);
        }
      } else if (item[childName] && item[childName].length > 0) {
        backarr(childId, item[childName]);
      }
    });
    return list;
  }
  return backarr(id, tree);
}
//找到所有子孙放到一个数组里面
export function selectAllChild(ids, list) {
  let child = [];
  // 查找指定id下所有子元素集合
  function nextChild(arr) {
    arr.forEach((item) => {
      if (item.children && item.children.length > 0) {
        child.push(...item.children.map((a) => a.id));
        nextChild(item.children);
      }
    });
  }
  // 找到指定id
  function findChild(ids, arr) {
    for (let item of arr) {
      if (item.id == ids) {
        if (item.children && item.children.length > 0) {
          child.push(...item.children.map((a) => a.id));
          nextChild(item.children);
          break;
        }
      } else if (item.children && item.children.length > 0) {
        findChild(ids, item.children);
      }
    }
    return child;
  }
  return findChild(ids, list);
}

如果大家有什么好的办法,评论区见!

Logo

前往低代码交流专区

更多推荐