史上最全,在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'}
          }
      },

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

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

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
下面是一个使用d3.js在Vue实现树形结构曲线连接的示例: 1. 安装d3.js 使用npm安装d3.js: ``` npm install d3 ``` 2. 在Vue组件导入d3.js 在Vue组件的`<script>`标签导入d3.js: ``` import * as d3 from 'd3'; ``` 3. 在Vue组件定义一个SVG元素 在Vue组件定义一个SVG元素,用于绘制树形结构: ``` <template> <svg ref="svg"></svg> </template> ``` 4. 在Vue组件的mounted钩子函数使用d3.js绘制树形结构Vue组件的mounted钩子函数使用d3.js绘制树形结构: ``` <script> export default { mounted() { const svg = d3.select(this.$refs.svg); const width = 500; const height = 500; const treeData = { name: 'A', children: [ { name: 'B', children: [ { name: 'C' }, { name: 'D' } ] }, { name: 'E', children: [ { name: 'F' }, { name: 'G' } ] } ] }; const treeLayout = d3.tree() .size([width, height]); const rootNode = d3.hierarchy(treeData); treeLayout(rootNode); const link = svg.selectAll('.link') .data(rootNode.links()) .enter() .append('path') .attr('class', 'link') .attr('d', d => { return `M${d.source.x},${d.source.y}C${d.source.x},${(d.source.y + d.target.y) / 2} ${d.target.x},${(d.source.y + d.target.y) / 2} ${d.target.x},${d.target.y}`; }); const node = svg.selectAll('.node') .data(rootNode.descendants()) .enter() .append('g') .attr('class', 'node') .attr('transform', d => `translate(${d.x},${d.y})`); node.append('circle') .attr('r', 5); node.append('text') .attr('x', 10) .attr('y', -10) .text(d => d.data.name); } } </script> ``` 这段代码首先定义了一个SVG元素,然后使用d3.tree()创建一个树形布局,再使用d3.hierarchy()创建一个层次结构。接着使用selectAll()创建节点和链接,使用enter()添加节点和链接,然后使用attr()设置样式和属性。最后使用path元素绘制贝塞尔曲线连接节点。 上面的代码可以画出一个简单的树形结构,你可以根据自己的需求修改数据和样式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值