.wxml 文件
<view wx:for="{{tree}}" wx:key="id" class="tree-container">
<view class="tree-item">
<text class="iconfont {{item.open ? '+' : '-'}} tree-dropdown" data-index="{{index}}" bindtap="trigger" />
<text class="tree-lable" data-info="{{item}}" bindtap="handleSelect">{{item[label]}}</text>
<text wx:if="{{value == item[selectKey]}}" class="iconfont icon-selected tree-selected">√</text>
</view>
<!-- 二级菜单 -->
<tree wx:if="{{item.open && item[children] && item[children].length > 0 }}" dataTree='{{ item[children] }}' label="{{label}}" children="{{children}}" model:value="{{value}}" selectKey="{{selectKey}}" bind:select="chilrenSelect" />
</view>
.json 文件
{
"component": true,
"usingComponents": {
"tree": "/components/customComponents/tree"
}
}
.js 文件
Component({
options: {
addGlobalClass: true,
},
properties: {
dataTree: { // 树形结构数据
type: Array,
value: []
},
value: { // 选择值
type: String,
value: ''
},
selectKey: { // 选择字段属性
type: String,
value: 'id'
},
label: { // 显示名称属性
type: String,
value: 'name'
},
children: { // 子级属性
type: String,
value: 'children'
},
open: { // 是否展开全部节点(数据中open优先)
type: Boolean,
value: false
}
},
observers: {
'dataTree': function (params) {
this.setData({
tree: this._initData(params)
})
}
},
data: {
tree: []
},
methods: {
_initData (nodes) {
nodes.forEach(el => {
if (el.open == undefined) el.open = this.properties.open // 是否展开
const children = this.properties.children
if (el[children] && el[children].length > 0) el[children] = this._initData(el[children])
})
return nodes
},
// 选择事件
handleSelect (e) {
const info = e.currentTarget.dataset.info
let value = ''
if (info[this.data.selectKey] != this.data.value) value = info[this.data.selectKey]
// 更新选择
this.setData({ value })
this.triggerEvent('select', info)
},
// 选择冒泡事件
chilrenSelect (e) {
const data = e.detail
this.triggerEvent('select', data)
},
// 展开、收起
trigger (e) {
const index = e.target.dataset.index
this.data.tree[index].open = !this.data.tree[index].open
this.setData({ tree: this.data.tree })
}
}
})
.wxss 文件
.tree-container {
display: flex;
flex-direction: column;
padding-left: 24rpx;
}
.tree-item {
display: flex;
}
.tree-dropdown {
padding: 24rpx;
font-size: 32rpx;
}
.tree-lable {
flex: 1;
line-height: 3;
font-size: 28rpx;
max-width: 510rpx;
}
.tree-selected {
color: #18C984;
font-size: 50rpx;
padding: 12rpx 24rpx;
}
使用方式
<view>
<tree dataTree="{{tree}}" model:value="{{value}}"/>
</view>
data: {
value:'',
tree: [
{
id: 1,
name: '001',
open: true,
children: [{
id: 2,
name: '001-01',
children: [{
id: 3,
name: '001-01-01',
children: []
}]
}]
}
]
}
总结:
1、小程序中未提供元素节点动态插入,不能 js 动态挂载元素 (只提供节点信息查询方式)。
2、树形菜单核心在于递归,本组件用组件调用自身实现递归。
3、组件在这里只实现单选 √ ,需要多选的自行发挥