史上最全,在vue中使用zTree实现树型结构(第二篇)

本文详细介绍了在Vue项目中使用ztree遇到的问题,如滚动条处理、节点展开控制、文本截断提示、数据过滤、节点操作(复制、移动)以及特定需求如背景色显示和节点编辑。作者还提供了自定义组件和解决滚动条遮挡右键菜单的方法。
摘要由CSDN通过智能技术生成

上一次写ztree的使用,还是在2年前,如今我已经是个成熟的ztree的使用者了,今天我们再来详细的介绍一下,如何在vue中使用ztree;

先来看下我写好的效果

需要解决的问题:

1.左侧导航栏有滚动条,因为overflow:hidden属性,右键节点出现菜单不能被遮住

2.点击展开节点,默认一次要展开5个层级节点(难点)

3.对于文件名称超长的文本,需要显示...,对只有超长的文本鼠标hover的时候出现tips提示(有技巧)

4。对于不存在接口当中的数据,但是我页面又需要展示,也就是节点的操作(熟悉ztree的都知道,节点操作其实是最简单的,只要按照ztree的规则组装节点,什么复制节点,移除节点,添加节点巴拉巴拉都是小问题);我的右键菜单中,大家可以看到有复制/移动功能,且我页面上是有三颗没有任何关联的树,当我使用复制/移动功能将某一个节点移动到其他树上的时候,需要将当前树的节点移除,而目标树新增一个节点(其实实现真的超级简单了)

5.我们设计原本给我提了一个需求,要求ztree选中节点的背景色要包含展开和收缩的小图标,我以为很简单,事实也很简单,不过要熟悉官网

6.每个层级溢出的文本长度不一致(图3),就是每一个层级溢出隐藏的长度需要在可视范围,这个应该很少用到吧,这里就不讲了

7.文件节点的新建和修改,都是ztree的onrename 输入框失焦事件,如何区分修改和新建,利用ztree提供的dataFilter方法,可以将接口返回的数据自定义添加自己所需要的属性

图1

图2

    

    data() {
        return {
            treeObj: '',
            settings: {
                data: {
                    simpleData: {
                        enable: false,//看接口返回的数据是简单数据类型还是标签的json数据
                    },
                    key: {
                        name: 'name', //节点显示名称后台所定义的字段
                        isParent: 'hasChildren' //接口数据定义父子关系的字段
                    }
                },
                callback: {
                    onClick:this.zTreeOnClick,
                    onRename: this.zTreeOnRename,//输入框失焦事件
                    // beforeEditName: this.zTreeBeforeEditName,//重命名之前的事件
                    beforeRename:this.ztreeBeforeRename,//input输入框失焦或者按住enter的事件
                    onRightClick: this.zTreeOnRightClick,//右键点击出现菜单
                    onNodeCreated: this.zTreeOnNodeCreated,//
                    beforeAsync: this.beforeAsync,//异步请求前回调
                    onAsyncSuccess: this.onAsyncSuccess,//异步请求成功之后的回调
                    onAsyncError: this.onAsyncError,//异步失败的回调
                    beforeExpand: this.zTreeBeforeExpand, //节点展开前的回调
                    onCollapse: this.zTreeOnCollapse, //节点收起的回调
                },
//异步节点所触发的接口,如果是同步则不需要,拿到数据直接渲染
                async: {
                    enable: true,
                    contentType: "application/json",
                    type: 'post',
                    url: "/cross/resourcemanagerservice/api/resource/container/get",
                    dataType: 'json',
                    // autoParam: ["id=''"],
//接口所需要的参数
                    otherParam:{"needParent":false,"recursively":false,"userId":this.userId,"tenantId":this.tenantId,parentId: this.$route.name == 'assetlibrary' ? 'LIBRARY_PUBLIC_DOMAIN_' : '_PUBLIC_DOMAIN_'},
                    dataFilter: function (treeId, parentNode, data) {
                        data.containerList.forEach(node => {
//这里添加节点是重新命名还是新建的标识
                            node.isEdit = false;
                        });
                        return data.containerList;
                    }
                },
                edit: {
                    enable: true,
                    showRemoveBtn: false,
                    showRenameBtn: false,
                    drag:{
                      isCopy:false,
                      isMove:false
                    },
                    editNameSelectAll: true
                },
                view: {
                    addDiyDom:this.addDiyDom, //自定义页面展现树节点的结构
                    addHoverDom: this.addHoverDom,//鼠标hover节点的时候的钩子函数
                    removeHoverDom: this.removeHoverDom, //鼠标移除节点所触发的钩子函数,与addhoverdom配套使用
                    showLine:false,//是否显示节点的链接线
                    showTitle:false,//是否显示节点的title属性
                    fontCss:{'color':'#333'} //设置节点的字体样式
                }
            },
        }
    },

 在mounted中初始化树形结构

    mounted() {
        // ztree-public为你装载树型结构的dom的名称
        this.treeObj = $.fn.zTree.init($("#ztree-public"), this.settings);
    },

 问题2,5的解决方法:背景色包含整个节点,包含收缩和展开的小图标,文件夹名称超长显示tips

        addDiyDom(treeId, treeNode){
            // 此操作是为了将节点的展开和收起按钮包在背景色当中
            var switchObj = $("#" + treeNode.tId + "_switch"), //节点的展开dom
                icoObj = $("#" + treeNode.tId + "_ico"); //节点图标文件夹
            switchObj.remove();
            icoObj.before(switchObj); //再每个ico前面插入节点
            // 修改node_name的结构,这里是文件夹名称超长,鼠标hover超长文本的时候核心方法,同样也是修改ztree渲染节点信息的结构来实现
            var nodeName = $("#" + treeNode.tId + "_span")
            var newDom = $("<div class='node-name-box' id='node_name-box" + treeNode.tId
                + "'></div>");
            nodeName.remove()
            icoObj.after(newDom)
            newDom.append(nodeName)
        },

问题1的解决方法:

其实在vue3中,这很容易实现,vue3的新特性teleport组件可以将dom结构渲染在任何你想要的位置,但是我是vue2,所以自己写了个组件,去模拟teleport组件

<script>
    export default {
      // 模拟vue3的新特性
        name: 'teleport',
        props: {
            /* 移动至哪个标签内,最好使用id */
            to: {
                type: String,
                required: true
            }
        },

        mounted() {
            document.querySelector(this.to).appendChild(this.$el)
        },

        destroyed() {
            document.querySelector(this.to).removeChild(this.$el)
        },

        render() {
            return <div>{this.$scopedSlots.default()}</div>
        }
    }
</script>

使用方式如下:

          <teleport to="body">
            <div id="rMenu">
                <ul>
                  <li id="m_del" @click="removeTreeNode();">删除</li>
                  <li id="m_check" @click="updateTreeNode();>重命名</li>
                  <li id="m_copy" @click="copypasteTreeNode();">复制/移动到...</li>
                  <li id="m_setroles" @click="setaclTreeNode();">设置权限</li>
                  <li id="m_lifecycle" @click="setlifeTreeNode();">设置生命周期</li>
                  <li id="m_space" @click="dialogSpace = true">设置空间配额</li>
                </ul>
            </div>
            <!-- 当节点名称过长,鼠标hover显示tips -->
            <div id="rMenu-name">
              {{hoverDomName}}
              <span class="box-list-arrow"></span>
            </div>
          </teleport>

问题4,很简单,看官网,节点的操作方法,非同一颗树之间节点的复制和粘贴,其实给每个树绑定ref属性,然后去调用每个树的方法就行了,类似这样

我懒,就写这么多吧

问题2:我觉得除了我们产品,应该没有哪个产品会提这么变态的需求吧,也不想讲了,有需要的可以提供思路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值