小程序树形组件实现(带连线的哦)

1,391 阅读1分钟

公司有一个需求就是在小程序上要实现一个树形组件,我一想,这事有点难啊,我之前都没见过在小程序上有树形组件的,这怎么搞,还要连线,我好像搞不了。百度了许多组件看了看,好像有些想法了,那就开始搞,哈哈哈。

主要思路应该是先利用组件的递归调用,先实现一个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;
}