zTree的使用踩坑记录(编辑、新增)

2023/5/26 zTree

原文地址 (opens new window) 最近做了一个功能,在vue中使用到了zTree,要求实现树节点的新增和编辑,即鼠标移到节点上的时候显示出这两个按钮,点编辑的时候节点会变成输入框可直接输入,点新增的时候会在该节点的子节点中新增一个节点,并显示为可编辑状态。

做的过程中踩了不少坑,记录下。

官网API地址 (opens new window)(直接看API比在网上找乱七八糟的代码有用多了)

# 首先是先在main.js引入ztree插件

记住,如果有用到ztree自带的编辑或删除,一定要记得引入 jquery.ztree.exedit.min;同时,ztree没有添加节点的按钮,需要我们自己创建

# 页面

html部分只需要:

<ul id="resourceTree" class="ztree"></ul>
1

# 代码

# 配置

setting: {	
	//在这里配置 添加按钮(自定义)
	view: {
	    addHoverDom: this.addHoverDom, //当鼠标移动到节点上时,显示用户自定义控件
	    removeHoverDom: this.removeHoverDom, //离开节点时的操作
	},
	
	//在这里配置编辑或删除按钮,删除按钮没有写,有需要的话移步官网API~
	edit:{
	    enable: true,
	    editNameSelectAll: true,
	    showRemoveBtn: false, //删除按钮不显示
	    showRenameBtn: this.showRenameBtn, //编辑按钮
	    renameTitle: '编辑' //编辑按钮hover上去后显示的title提示
	},
	
	data: {
	    simpleData: {
	        enable: true,
	        idKey: "bkid",  //配合后端返回的字段名称填写,这里是节点id
	        pIdKey: "bkpid"  //这里是父节点id
	    },
	    key: {
	        name: "bkname"  //配合后端返回的字段名称填写,展示的节点名称
	    }
	},
	
	callback: {
	    onClick: this.selectChange,  //节点选中事件
	    beforeRename: this.beforeRename,  //用于捕获更新节点名称之前,这里可以用来写判断节点名称不为空
	    onRename: this.onRename  //更新节点名称事件
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 加载树的数据

getResourceTree(treeNode){
    var thiz = this;
    this.$store.dispatch('axios_req',
        {
            type:'post',
            url: 'tree.do',
            async: false,
            data : {},              //直接传入data
            success : function(res) {
                thiz.resourceTree = res.data.data;
                thiz.initTree();
                //这里是新增完节点后,刷新tree,定位到刚刚新增的那个节点,并直接进入编辑状态,这里的代码视实际操作情况写
                if(treeNode){
                    var zTree = $.fn.zTree.getZTreeObj("resourceTree");
                    var node = zTree.getNodesByParam('bkid', treeNode.bkid)
                    zTree.expandNode(node[0], true, false);//展开父节点
                    zTree.selectNode(node[0].children[0]);//选中当前节点
                    zTree.editName(node[0].children[0]);//进入编辑状态
                }
            },
            fail : function(err) {
                console.log('out fail : ' + err);
            }
        }
    )
},
initTree(){
	//非异步加载模式下,无子节点的父节点设置 open=true 后,可显示为展开状态,但异步加载模式下不会生效
    $.fn.zTree.init($("#resourceTree"), this.setting, this.resourceTree);
    var treeObj = $.fn.zTree.getZTreeObj("resourceTree");
    var nodes = treeObj.getNodes();
    for (var i = 0; i < 2; i++) { //设置节点展开
        treeObj.expandNode(nodes[i], true, false, true);
    }
    //treeObj.expandAll(false);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 编辑节点

//判断节点名称不能为空
beforeRename(treeId, treeNode, newName) {
    var thiz = this;
    if (newName.trim().length == 0) {
        $.fn.zTree.getZTreeObj("resourceTree").cancelEditName();
        thiz.$Message.info('节点名称不能为空');
        return false;
    }
    return true;
},
//ztree编辑事件
onRename(treeId, treeNode, newName){
    var thiz = this;
    thiz.$store.dispatch('axios_req',
        {
            type:'post',
            url: 'edit.do',
            data : {
                
            },              //直接传入data
            success : function(res) {
            
            },
            fail : function(err) {
                console.log('out fail : ' + err);
            }
        }
    )
},

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 添加节点

//ztree新增节点
addHoverDom(treeId, treeNode){
    var thiz = this;
    var sObj = $("#" + treeNode.tId + "_span");
    if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length>0) return;

    var addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增' οnfοcus='this.blur();'></span>"; //定义添加按钮
    sObj.after(addStr); //加载添加按钮
    var btn = $("#addBtn_"+treeNode.tId);

    //绑定添加事件,并定义添加操作
    if (btn) btn.bind("click", function(event){
        event.stopPropagation();
        var zTree = $.fn.zTree.getZTreeObj("resourceTree");
        //将新节点添加到数据库中
        var name = '';
        if(treeNode.children){
            name = '默认名称' + (treeNode.children.length + 1)
        }else{
            name = '默认名称1';
        }
        thiz.$store.dispatch('axios_req',
            {
                type:'post',
                url: 'add.do',
                data : {
                
                },              //直接传入data
                success : function(res) {
                    if(res.data.success){
                        //刷新树
                        thiz.getResourceTree(treeNode);
                    }
                },
                fail : function(err) {
                    console.log('out fail : ' + err);
                }
            }
        )

    });
},
//ztree移除新增节点
removeHoverDom(treeId, treeNode){
    $("#addBtn_"+treeNode.tId).unbind().remove();
},

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 节点选中

//ztree选中事件
selectChange(event, treeId, treeNode){
    var thiz = this;
    thiz.rowData = treeNode;
    thiz.controlList = true;
},

1
2
3
4
5
6
7

# 功能到这个差不多就结束了,另外树的样式修改我选择了自己写css直接覆盖,可参考

//less
@treeCloseIcon: url('../../assets/dispatch/tree_close_blue.png');
@treeOpenIcon: url('../../assets/dispatch/tree_open_blue.png');
@treeFileIcon: url('../../assets/dispatch/tree_file_blue.png');
@treeFileIconHov: url('../../assets/dispatch/tree_file_hov.png');
@startP: #677294;

/* 隐藏原始的文件夹图标 */
.ztree li span.button.ico_close{
    display: none;   
}
.ztree li span.button.ico_open{
    display: none;     
}

/* 节点名称样式 */
.ztree .node_name{
    color: @startP;
    margin: 4px 1px;
    padding: 0 4px;
    height: 20px;
    line-height: 20px;
    display: inline-block;
}

/* 编辑时候的输入框 */
.ztree .node_name input{
    width: 100%;
    height: 100%;
}

/* 节点展开 前面的加号图标修改 */
.ztree li span.button.center_close,
.ztree li span.button.root_close,
.ztree li span.button.bottom_close{
    background: @treeCloseIcon !important;
    background-size: 100% 100% !important;
    width: 16px;
    height: 16px;
    margin-top: 6px;
}

/* 节点关闭 前面的减号图标修改 */
.ztree li span.button.center_open,
.ztree li span.button.root_open,
.ztree li span.button.bottom_open{
    background: @treeOpenIcon !important;
    background-size: 100% 100% !important;
    width: 16px;
    height: 16px;
    margin-top: 6px;
}

/* 节点行高拉大 */
.ztree li a{
    height: 28px;
    line-height: 28px;  
}

/* 最后一级的节点图标修改 */
.ztree li span.button.ico_docu{
    background: @treeFileIcon !important;
    display: inline-block;
    vertical-align: middle;
    margin-top: -6px;
}

/* 最后一级的节点图标 前面的虚线位置修改(因为行高被我改大了...) */
.ztree li span.button.switch{
    display: inline-block;
    vertical-align: middle;
    margin-top: 5px;
}

/* 节点选中样式 */
.ztree li a.curSelectedNode{
    background-color: transparent;
    border: 1px solid transparent;
    opacity: 1;
}
.ztree li a.curSelectedNode .node_name{
    background-color: #008FFF;
    border: none;
    color: #fff;
}
.ztree li a.curSelectedNode .ico_docu{
    background: @treeFileIconHov !important;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
最后更新时间: 2023/7/16 15:32:35