公司有一个需求就是在小程序上要实现一个树形组件,我一想,这事有点难啊,我之前都没见过在小程序上有树形组件的,这怎么搞,还要连线,我好像搞不了。百度了许多组件看了看,好像有些想法了,那就开始搞,哈哈哈。
主要思路应该是先利用组件的递归调用,先实现一个wxml页面实现,然后在想办法写线条,这里我是先把线条都画出来,然后在动态计算最后一个子节点的高度,最后用fff的颜色去覆盖掉多余的线条。 主要代码如下
wxml:
<view class="tree_root">
<view class="leaf">
<!-- <text class="icon" wx:if='{{ isBranch }}' bindtap='toggle'>{{open?'-':'+'}}</text> -->
<block wx:if='{{ isBranch }}'>
<image wx:if="{{open}}" src="/assets/icons/up.png" bindtap='toggle'></image>
<image wx:else src="/assets/icons/down.png" bindtap='toggle'></image>
</block>
<!-- <text wx:else class="icon">*</text> -->
<text bindtap='tapItem' data-itemid='{{ model.id }}' class="{{isSelect?'leef act':'leef'}}">{{ model.text }}</text>
</view>
<view style='padding-left: 50rpx;' wx:if='{{ isBranch }}' hidden='{{ !open }}'>
<block wx:for='{{ model.nodes }}' wx:key='id'>
<block wx:if="{{model.nodes.length-1==index}}">
<view class="{{isBranch?'last_child':''}}">
<treeview model='{{ item }}'></treeview>
</view>
</block>
<block wx:else>
<treeview model='{{ item }}'></treeview>
</block>
</block>
</view>
</view>
json:
{
"component": true,
"usingComponents": {
"treeview": "../treeview/treeview"
}
}
js:
// pages/components/treeview/treeview.js
Component({
properties: {
model: Object,
selArr:Array
},
data: {
open: true,
isBranch: false,
isSelect:false
},
methods: {
toggle: function(e) {
if (this.data.isBranch) {
this.setData({
open: !this.data.open,
})
}
},
tapItem: function(e) {
var itemid = e.currentTarget.dataset.itemid;
// console.log('组件里点击的id: ' + itemid);
this.setData({
isSelect:!this.data.isSelect
})
// 向外传递当前点击节点的id,配合调用组件的地方,可实现点击节点选择
this.triggerEvent('tapitem', { itemid: itemid });
}
},
ready: function(e) {
this.setData({
isBranch: Boolean(this.data.model.nodes && this.data.model.nodes.length),
});
// console.log(this.data);
},
})
wxss:
/* components/treeview/treeview.wxss */
.leef {
display: inline-block;
border: 1px solid #ddd;
border-radius: 7rpx;
height: 56rpx;
line-height: 56rpx;
padding: 0 12rpx;
color: #007BC7;
}
.act{
border: 1px solid #007BC7;
background: #007BC7;
color: #fff;
}
.icon{
width: 30rpx;
height: 30rpx;
display: inline-block;
line-height: 30rpx;
margin-right: 16rpx;
border: 1px solid #ddd;
text-align: center;
color: #ddd;
border-radius: 6rpx;
font-size: 24rpx;
background: #fff;
}
.leaf{
margin-bottom: 20rpx;
position: relative;
}
.leaf image{
width: 30rpx;
height: 30rpx;
margin-right: 16rpx;
}
.leaf::before{
width: 34rpx;
height: 0;
content: '';
border-top: 1px solid #ddd;
left: -36rpx;
top: 26rpx;
position: absolute;
}
.tree_root{
position: relative;
}
.tree_root::before{
height: calc(100% - 56rpx);
/* min-height: 56rpx; */
content: '';
position: absolute;
left: 14rpx;
top: 34rpx;
border-left: 1px solid #ddd;
}
.last_child{
position: relative;
}
.last_child::before{
height: calc(100% - 46rpx);
content: '';
position: absolute;
left: -38rpx;
top: 28rpx;
border-left: 6rpx solid #fff;
}