实现原理:利用自定义组件递归使用,也就是自定义组件自引用
因为树状图的数据是从后台获取的,没有办法知道具体层级,但是他们的结构都是相同的,所以在自定义的组件中再去引用自身来实现需求
1.先写好树形菜单的样式结构,可以自定义假数据,将静态写好
2.自定义components,将写好的样式结构丢进去,子元素重复的结构就不需要了
3.父组件传递数据,自定义组件进行操作
可以去官网看看组件使用:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/
自定义组件:
<!-- wxml中的结构 -->
<view class='ul re'>
<view class='li li{{item.id}}' wx:if="{{treedata.length>0}}" wx:for="{{treedata}}" wx:key="{{item.id}}">
<view class='dai bb'>
<!-- 如果没有子级不需要显示+ -符号 ,默认显示加号,即id和pid是不等的-->
<view class='plus' bindtap='toggle' data-id='{{item.id}}' data-pid='{{item.pid}}' wx:if="{{item.children!=undefined&&item.children!=null&&item.children.length>0}}">{{item.id!=item.pid?'+':'-'}}</view>
</view>
<view class='span span{{item.id}} re' data-id="{{item.id}}" bindtap='myInfo' style="background-color:{{item.deathtime==null?'':'#9f9f9f'}}">
<view class='name'>{{item.name}}</view>
<view class='texts bb' wx:if='{{item.deathtime!=null}}'>故</view>
</view>
<!-- wx:if 如果没有子级就不需要去渲染了 hidden是用来后面做折叠操作的 -->
<view class='ul' data-id='{{item.id}}' data-pid='{{item.pid}}' wx:if="{{item.children!=undefined&&item.children!=null&&item.children.length>0}}" hidden="{{item.id==item.pid}}">
<servant treedata="{{item.children}}"></servant>
</view>
</view>
</view>
.ul {
padding-left: 66rpx;
position: relative;
}
.li {
list-style-type: none;
margin: 0;
padding: 15rpx 100rpx 0;
position: relative;
}
.li::before, .li::after {
content: '';
left: -40rpx;
position: absolute;
right: auto;
}
.li::before {
border-left: 1rpx solid #999;
bottom: 100rpx;
height: 100%;
top: 0;
width: 2rpx;
}
.li::after {
border-top: 1rpx solid #999;
height: 40rpx;
top: 50rpx;
width: 140rpx;
}
.li .span {
width: 153rpx;
height: 66rpx;
text-align: center;
line-height: 66rpx;
border: 1rpx solid #999;
border-radius: 35rpx;
display: inline-block;
padding: 6rpx 16rpx;
text-decoration: none;
font-size: 32rpx;
position: relative;
}
.ul>.li1::before, .ul>.li1::after {
border-top: 1rpx solid #999;
height: 40rpx;
top: 50rpx;
width: 140rpx;
border-left: 0;
}
.li:last-child::before {
height: 52rpx;
}
.texts {
width: 45rpx;
height: 45rpx;
line-height: 45rpx;
position: absolute;
right: -8%;
top: -28%;
border-radius: 50%;
background-color: #afafaf;
font-size: 27rpx;
color: #fff;
}
.dai {
position: absolute;
font-size: 27rpx;
left: -15rpx;
top: 34rpx;
background-color: #fff;
z-index: 999;
padding: 0 6rpx;
display: flex;
align-items: center;
}
.plus {
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
border-radius: 50%;
background-color: #5c5c5c;
}
//在组件json文件中,需要声明component为true;组件中自引用需要声明usingComponents
{
"component":true,
"usingComponents":{
"servant":"/components/treeMenu/treeMenu" // 组件路径
}
}
// 组件的js文件
// 组件的属性值和内部数据将被用于组件 wxml 的渲染,其中,属性值是可由组件外部传入的
Component({
// 组件的属性列表
properties: {
// 定义属性,属性值可以在组件使用时指定
treedata: {
type: Array,
value: []
}
},
// 组件内的初始数据
data: {
mid: '', // 存储原来的pid
},
// 组件的方法列表
methods: {
//实现折叠效果 同时改变页面'+' '-'符号显示,返回的数据中每一项的id和pid是不等的
toggle: function(e) {
var id = e.currentTarget.dataset.id; //原来的id
var pid = e.currentTarget.dataset.pid; //原来的pid
if (!this.data.mid) {
this.setData({
mid: pid
})
}
for (var i in this.properties.treedata) {
if (this.properties.treedata[i].id == id) {
if (this.properties.treedata[i].id == pid) {
this.setData({
[`treedata[${i}].pid`]: this.data.mid, // es6模板语法
})
} else {
this.setData({
[`treedata[${i}].pid`]: id,
})
}
}
}
}
},
// 组件所在页面的生命周期函数
ready: function() {
}
})
组件定义完成后,在其他页面中使用:
// 1. 页面json文件中需要声明
{
"usingComponents":{
"servant":"/components/treeMenu/treeMenu" //自定义组件路径
}
}
// 2. 页面js中定义数据(根据需求做请求操作)
Page({
data:{
treedata:[]
}
})
// 3. 组件传值 通过组件定义的treedata进行数据传递,组件接收存储使用其渲染
<view>
// 组件的属性treedata接收页面传递的数据
<servant treedata='{{treedata}}'></servant>
</view>
效果图: