工作原因,微信小程序需要一个功能类似于elemenui中的tree组件,找了好多ui组件库没有能直接用的,最后自己写了一套,封装成组件,中心技术是组件本身递归,只需要在父级页面传“树列表数据”和“选中的节点id”就可以用了。
tree组件
tree.wxml
<!--common/tree/tree.wxml-->
<view wx:for="{{tree}}" wx:key="deptId">
<!-- 一级 -->
<view style="margin-left: {{treeListIndex*24}}rpx" >
<view class="tree-item">
<view bindtap="isOpen" data-index="{{index}}" wx:if="{{item.children && item.children.length > 0 || item.userList && item.userList.length>0}}" class="iconfont {{item.open ? 'icon-out' : 'icon-in'}}" style="color: #E6A23C;"></view>
<view class="iconfont icon-in" wx:else style="color: #E6A23C;"></view>
<view class="tree-item-name" >
<text class="tree-item-title">{{item.deptName}}</text>
</view>
</view>
<view wx:if="{{item.userList && item.userList.length>0 && item.open}}" class="tree-user-item" >
<view wx:for="{{item.userList}}" wx:key="userId" class="tree-user-item-item" catchtouchmove="preventD" catchtap="select" data-item="{{item}}" data-index="{{index}}">
<view class="tree-user-avater-item" >
<view>{{item.nickName}}</view>
<view>{{item.nickName}}</view>
</view>
<view class="iconfont icon-selin" wx:if="{{item.status == 1}}" style="color: #2677FC;"></view>
<view class="iconfont icon-selout" wx:if="{{item.status == 0}}"></view>
</view>
</view>
</view>
<tree wx:if="{{item.children && item.children.length > 0 && item.open }}" ids="{{ ids }}" treeData='{{ item.children }}' bind:getIds="nodeGetIds" data-index="{{index}}" data-node="{{item.children}}" isOpenAll="{{true}}" treeListIndex="{{treeListIndex+1}}" />
</view>
tree.js
// common/tree/tree.js
const app = getApp()
Component({
/**
* 组件的属性列表
*/
properties: {
treeData: {
type: Array,
value: []
},
ids: {
type: Array,
value: [],
},
treeListIndex: {
type: Number,
value: 1
},
isOpenAll: { // 是否展开全部节点
type: Boolean,
value: true
}
},
/**
* 组件的初始数据
*/
data: {
tree: [],
},
observers: {
'treeData':function(params) {
this.setData({
tree: this._init(params)
})
},
'ids':function(params) {
this.setData({
tree: this._uploadTree(params, this.data.tree)
})
},
},
/**
* 组件的方法列表
*/
methods: {
isOpen(e) {
const open = 'tree[' + e.currentTarget.dataset.index + '].open'
this.setData({
[open]: !this.data.tree[e.currentTarget.dataset.index].open
})
},
_init(node) {
let that = this;
node.forEach(element => {
if(element.checked == undefined) element.checked = 0;
element.open = this.properties.isOpenAll;
if(element.children && element.children.length > 0) element.children = this._init(element.children)
})
return node
},
_uploadTree(ids, tree){
tree.forEach(element => {
if(element.userList && element.userList.length > 0) {
element.userList.forEach(r => {
if(ids.indexOf((Number(r.userId))) > -1) {
r.status = 1
} else {
r.status = 0
}
})
}
})
return tree
},
// 选择
select(e) {
let item = e.currentTarget.dataset.item
this.triggerEvent('getIds', item.userId)
},
nodeGetIds(e) {
this.triggerEvent('getIds', e.detail)
}
}
})
tree.wxss
/* common/tree/tree.wxss */
@import "/utils/iconFont.wxss";
.tree-item{
display: flex;
align-items: center;
margin: 10rpx 0;
}
.tree-item-name{
margin-left: 20rpx;
}
.tree-item-title{
font-size: 32rpx;
color: #303133;
}
.tree-user-item{
/* display: flex;
align-items: center; */
margin: 20rpx 0;
box-sizing: border-box;
}
.tree-user-item-item{
display: flex;
align-items: center;
justify-content: space-between;
margin: 30rpx 0;
}
.tree-user-avater-item{
display: flex;
align-items: center;
font-size: 32rpx;
color: #303133;
}
.tree-user-avater-item>view:nth-of-type(1) {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
font-size: 26rpx;
color: #fff;
text-align: center;
line-height: 64rpx;
margin-right: 10rpx;
background-color: #2677FC;
}
tree.json
{
"component": true,
"usingComponents": {
"tree": "/common/tree/tree"
}
}
父级页面
sel-people.wxml
<tree treeData="{{treeData}}" ids="{{ids}}" treeListIndex="{{1}}" isOpenAll="{{true}}" bind:getIds="getIds"></tree>
sel-people.json
{
"usingComponents": {
"tree": "/common/tree/tree"
}
}
sel-people.js
// pages/sel-people/sel-people.js
const app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
contentHeight: app.globalData.contentHeight,
navColor: '#fff',
title: '',
backStatus: true,
// 模拟接包时候的json数据
treeData: [
{
"deptId": "1",
"deptName": "经建",
"userList": [
{
"userId": 1,
"userName": "admin",
"nickName": "管理员"
},
{
"userId": 2,
"userName": "corner",
"nickName": "星辰"
}
],
"children": [
{
"deptId": "2",
"deptName": "弘德云",
"userList": [
{
"userId": 3,
"userName": "admin1",
"nickName": "管理员1"
},
{
"userId": 4,
"userName": "corner1",
"nickName": "星辰1"
}
],
"children": [
{
"deptId": "3",
"deptName": "招投标",
"userList": [
{
"userId": 5,
"userName": "admin1",
"nickName": "管理员2"
},
{
"userId": 10,
"userName": "corner1",
"nickName": "星辰2"
}
]
}
]
}
]
}
],
ids: [1]
},
getIds(e) {
// 判断tree组件传过来的id,选中or未选中
let id = e.detail
if(this.data.ids.indexOf(Number(id)) > -1) {
this.data.ids.splice(this.data.ids.indexOf(Number(id)), 1)
} else {
this.data.ids.push(Number(id))
}
this.setData({
ids: this.data.ids
})
console.log(this.data.ids)
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
})
以下是tree组件需要的icon图标,自己去矢量库下载就好
以下是成品图
文章来源:https://www.toymoban.com/news/detail-790864.html
感谢大家!!!文章来源地址https://www.toymoban.com/news/detail-790864.html
到了这里,关于微信小程序自定义tree组件,拿走直接用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!