Bootstrap

史上最全,在vue中使用ztree实现树形结构(第三篇)

在公司呆了4年,现在想来最深的感受就是,凡是涉及到树性结构的,统统选择ztree准没错,我是ztree的忠实爱好者

再来看一下我们产品有啥新的树结构需求吧 

首先看上面这个图,可能和ztree联系不起来对不对,不要怀疑,上面就是用ztree来实现的,只不过dom是我们自己定义的而已,可能很多人忽略了ztree的name属性,其实这个属性非常重要,可能很多人觉得,如果需要自己自定义dom,为什么不在ztree提供的addDiyDom中去操作呢?

首先我们来看一下ztree官网对addDiyDom的介绍,官网上解释的说,用在节点上固定显示用户自定义控件,只是针对空间的显示,对于博主这种整个结构都和ztree大相径庭来说并不适用,而且大数据量的节点加载肯定会影响初始化性能


所以,我们只需要改变name属性即可

        settings: {
          data: {
              simpleData: {
                  enable: false,
              },
              key: {
                  name: 'ztreename',  //ztree的name属性,这里根据真是接口去设置
                  isParent: 'hasChildren'
              }
          },
          callback: {
              beforeAsync: this.beforeAsync,//异步请求前回调
              onAsyncSuccess: this.onAsyncSuccess,//异步请求成功之后的回调
              onAsyncError: this.onAsyncError,//异步失败的回调
              onExpand: this.zTreeOnExpand,//节点展开后的事件回调
              onNodeCreated:this.ztreeOnNodeCreated,//节点创建的回调
              onClick: this.zTreeOnClick, //节点点击时的回调
              onCollapse: this.zTreeOnCollapse
          },
          async: {
              enable: true,
              // contentType: "application/json",
              type: 'get',
              url: this.getUrl(), //url支持一个函数,因为这里我的url是动态的,所以这里我使用的是函数
              dataFilter: (treeId, parentNode, data) =>{
                console.log(treeId,parentNode,data,'稍微')
                  // 当前是第一次加载
                  // 需要组装片段场景的时长
                  if(data.resourceTree.children.length > 0){
                    data.resourceTree.children.forEach((obj,obx)=>{
                      // 处理好要显示的tags
                      let arr = []
                      console.log(obj,'是哪个资源数据有问题')
                      if (obj.tag && obj.tag.tagCategory.length > 0) {
                        obj.tag.tagCategory.map((item, ind) => {
                          let key = Object.keys(item)[0]
                          if (item[key] && item[key][Object.keys(item[key])[0]].length > 0) {
                            item[key][Object.keys(item[key])[0]].map((sec, index) => {
                              if(obj[Object.keys(sec)[0]] && obj[Object.keys(sec)[0]].length>0){
                                obj[Object.keys(sec)[0]].forEach((its,index) => {
                                  its.refName = `tag_${sec}`+obj.id+index+its.tag+obx
                                  its.parrentAttrid = Object.keys(item)[0]
                                  its.attrid = Object.keys(sec)[0]
                                  its.name = sec[Object.keys(sec)[0]],
                                  its.className = tagClassLinkName.has(its.name) ? tagClassLinkName.get(its.name) : ''
                                  arr.push(its)
                                })
                              }
                            })
                          } else {
                            if(obj.tag[key] && obj.tag[key].length>0){
                              obj.tag[key].forEach((its,index) => {
                                its.refName = `tag_${key}`+obj.id+index+its.tag+obx
                                its.parrentAttrid = Object.keys(item)[0]
                                its.attrid = Object.keys(item)[0]
                                its.name = Object.keys(item[key])[0],
                                its.className = tagClassLinkName.has(its.name) ? tagClassLinkName.get(its.name) : ''
                                arr.push(its)
                              })
                            }
                          }
                        })
                      }
                      obj.arr = arr
                      let tagsHtml = ''
                      console.log(obj.arr,'当前组装的标签结构')
                      let wordTextWidth = 60 //tag标签的文本宽度
                      let tagWidth = 0 //当前装载标签容器的宽度
                      obj.showCount = 0
                      let levelClassName =''//用于判断当前数据是什么层级的,不是第一个层级就是片段
                      // 每个层级的宽度不一样,不能使用ccType来判断,因为第一级也有可能是场景和镜头,根据父元素判断
                      if(!parentNode){
                        // 没有父级
                        tagWidth = 737
                        levelClassName+='level0'
                      } else if(parentNode.level == 0){
                        tagWidth = 584
                        levelClassName+='level1'
                      } else if(parentNode.level == 1){
                        tagWidth = 449
                        levelClassName+='level2'
                      }
                        // 需要计算tag标签的宽度,超出显示+号
                        wordTextWidth += this.getTextWidth(ii.tag, `normal 14px ${this.computedStyles}`) + 42
                        console.log(wordTextWidth,ii.tag,'当前标签宽度')
                        // showCount一旦复制,就不再赋值 了
                        if(obj.showCount == 0){
                          if (wordTextWidth > tagWidth ){
                            obj.showCount = ix
                          } else {
                            tagsHtml+= `<span class="bgcolor ${themeColor}">${ii.tag}</span>`
                          }
                        }
                      })
                      // 需要判断是否显示+号
                      if(obj.showCount  != obj.arr.length-1 && obj.showCount  != 0){
                        // 需要显示
                        tagsHtml+=`<span class="bgcolor showMoreTag" data-flag="zk">+${obj.arr.length - obj.showCount}</span>`
                      }
                      // 组装提示html
                      let childBgNum = obj.childrenSum > 0? obj.childrenSum:''
                      // 处理好name属性
                      let nameStr = `<div class="detail-scene">
                        <div class="img-box-ztree">
                          <img alt="" src=${obj.iconUrl}  />
                          <span class="childBg ${levelClassName}">${childBgNum}</span>
                        </div>
                        <div class="right-tag-detail">
                          <div class="big-name-box">
                            <div class="name-box  ${levelClassName}">
                              <span>
                                ${obj.name}
                              </span>
                            </div>
                            <span class="viewDetails ${levelClassName}"">查看详情<i class="icon-viewdetail"></i></span>
                          </div>
                          <div>
                            <span>${obj.startTime}-${obj.endTime}</span>
                          </div>
                          <div class="tag-box">
                            ${tagsHtml}
                          </div>
                        </div>
                      </div>`
                      obj.ztreename = nameStr  //ztree的name属性是支持html,这里我们组装一个html赋值给数据,在setting中name属性取ztreename
                    })
                  }
                  if(!parentNode && data.resourceTree.children.length == 0){
                    this.isshowEmpty = true
                  }

                  return data.resourceTree.children
                  
              }
          },
          edit: {
              enable: true,
              showRemoveBtn: false,
              showRenameBtn: false,
              drag:{
                isCopy:false,
                isMove:false
              },
              editNameSelectAll: true
          },
          view: {
              nameIsHTML: true,
              addDiyDom:this.addDiyDom,
              showLine:false,
              showTitle:false,
              showIcon:false,
              fontCss:{'color':'#333'}
          }
      },

这样当最终结构渲染出来之后,修改对应的类名就行了。

最终的结构都出现了,再想去绑定各种事件就洒洒水了

;