ElementUI tree控件如何取得被选中的节点,以及父节点(即使没被全选)

需求有了变动,之前只需要提交被选中的叶节点的id数组,那时候直接通过官方的api【getCheckedKeys】直接拿到。现在要求也要将父节点的id也传过去。

卡壳了,看了Issues,不少网友都有这种需求,没看到靠谱的方法。

有个思路,先通过getCheckedKeys拿到子节点的id,然后去tree的data去一个个去遍历,存在的给父节点id取出来,最后重组所有已选中的id进行提交,但如果遇到N多级的咋办? 不会写了。。。

阅读 61.2k
12 个回答

今天遇见了同样的问题 运用的也是改源码的方法
官方给了两个方法 getCheckedNodes 和 getSelectedNodes 没有获取父级的
所以就自己新增了个方法 getCheckedAll 获取选中和父级的

clipboard.png


getCheckedAll:function(){

 return this.flatState.filter(function (e) {
    if(e.node.indeterminate){
        return e.node.indeterminate
    }
    return e.node.checked
}).map(function (e) {
    return e.node
})

}

打印e会很容易的看见 官方有标识的 套用之前的getCheckedNodes 的代码一下就能写出来最后再
this.$refs.tree.getCheckedAll() 就能获取了父级的对象了

this.$refs.tree.getNode(id).parent.data

elementUi 官方提供了一个方法是 getNode
图片描述

这个方法能获取到整个node

this.$refs.tree.getNode(id)

可以自己打印试试
图片描述

所以:this.$refs.tree.getNode(id).parent.data就是我们要找的父节点啦

官方v2.2.1版本已经提供获取半选中状态节点对象。
clipboard.png
具体实现思路:

// 1. 先合并选中/半选中节点Id,请求传给后台。
[].concat(this.$refs.menuListTree.getCheckedKeys(), [this.tempKey], this.$refs.menuListTree.getHalfCheckedKeys())

this.tempKey === -666666 // 临时key, 用于解决tree半选中状态项不能传给后台接口问题. # 待优化

// 2. 给tree绑定数据时,通过tempKey移除之前添加的半选中状态节点Id。
var idx = this.menuIdList.indexOf(this.tempKey)
if (idx !== -1) {
  this.menuIdList.splice(idx, this.menuIdList.length - idx)
}
this.$refs.menuListTree.setCheckedKeys(this.menuIdList)

详细实现代码,可在https://github.com/daxiongYan...查阅。

终于解决了
你找到node_modules/element-ui/lib/element-ui.common.js
在20106行 改if(node.checked)为if(node.checked||node.indeterminate)就可以了

tree绑定的数据是一个list,经过下面的函数computed出来的,保存的时候,我从这个list里面去拿的parentId

 function toTree(data, parent_id) {
    var tree = [];
    var temp;
    for (var i = 0; i < data.length; i++) {
      if (data[i].parentId == parent_id) {
        var obj = data[i];
        temp = toTree(data, data[i].id);
        if (temp.length > 0) {
          obj.children = temp;
        }
        tree.push(obj);
      }
    }
    return tree;
  }
      

我自己获取是这么写的

getPermissions() {
        let _this=this;
        let permissions=this.$refs.tree.getCheckedKeys();
        let ids=[];
        permissions.forEach(key=>{
          getParentId(key)
        })
        function getParentId(id) {
            let node=_this.list.find(item=>item.id==id)
            if(node.parentId==0){
              return
            }else{
              ids.push(node.parentId)
              getParentId(node.parentId)
            }
        }
        permissions=[...new Set([...permissions,...ids])]
        return permissions.join(',')
      },

改源码不太好,所以我用了笨办法,
思路就是拿到选中的code 后 ,遍历 整棵树, 然后把半选中的添加进去,编辑的时候去掉这些半选中的nodes

//同步树插件的半选中状态(参数: 树的data,选中的node列表,是添加还是删除,选中节点的关键字key,如果是null 就取整个node)
export const handleUpdateCheckds = (tree, checkeds, isAdd = true, checkKey = 'no') => {
    let findHalfCheckds = (item, checkeds, result = new Set()) => {
        if (item.children) {
            let node = [...item.children];
            while (node.length) {
                let data = node.shift();
                if (!item.isRoot) {
                    if (isAdd && checkeds.includes(data[checkKey] || data) && !checkeds.includes(item[checkKey] || item)) {
                        result.add(item[checkKey] || item);
                    } else if (!isAdd && !checkeds.includes(data[checkKey] || data) && checkeds.includes(item[checkKey] || item)) {
                        result.add(item[checkKey] || item);
                    }
                }
                if (data.children && data.children.length > 0) {
                    node = node.concat(data.children);
                }
                findHalfCheckds(data, checkeds, result);
            }
        }
        return result;
    };
    let result,
        halfCheckds = [...findHalfCheckds({
            isRoot: true,
            children: tree
        }, checkeds)];
    if (isAdd) {  //
        result = [...new Set(checkeds.concat(halfCheckds))];
    } else {
        result = checkeds.filter(item => !halfCheckds.includes(item));
    }
    //console.log(halfCheckds);
    return result;
};

可以和后台写上id可以根据层级进行传递
比如使用-进行连接

祖父级id-父级id-id-子集id

新手上路,请多包涵

我也是这个问题 准备直接改源码。你解决了么

新手上路,请多包涵

请问下,如何根据已有的选择的key,复原原来的选择,如果通过修改源码的方式设置以后,那份获取到的key的数据直接set应该是不对的- -

将tree控件的数据源在取下来之后变换一下,遍历treeSource 为每个node节点增加属性parentIds:"id1,id2,..."

新手上路,请多包涵

我有一个思路,我也亲测过,可以取得父节点id
一般返回来的子节点数据data中存有父id(parent_id),通过element 的getCheckedNodes方法可以获得选中节点就可以获得父id了。多简单

treeNodes = this.$refs.tree.getCheckedNodes(true);
treeKeys = this.$refs.tree.getCheckedKeys();

/**

子节点id
*/
for(var i = 0; i < treeKeys.length - 1; i++) {

ids[i] = treeKeys[i];
}
/**

选中子节点的父节点id
*/
for(var i = 0; i < treeNodes.length; i++) {

ids.push(treeNodes[i].parent_id);
}
ids = JSON.stringify(ids);

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏