在公司呆了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'}
}
},
这样当最终结构渲染出来之后,修改对应的类名就行了。
最终的结构都出现了,再想去绑定各种事件就洒洒水了