前言:微信小程序并没有提供这样的组件 ,vant也没有,就自己写了一个
支持懒加载和一次性加载
懒加载:父组件会接收到type来区分是点击的图标还是标题,点击图标拿到当前数据,进行查询子级数据赋值给组件即可,点击标题可做选中操作
技术点:
1、组件自身递归
2、父子间事件通信 (需要层层向上传递)
子组件:
wxml文件
<view class="tree-box">
<view style="padding-left: 30rpx">
<view class="item" wx:for="{{treeList}}" wx:key="*this">
<view class="item-icon-text">
<van-icon custom-style="{{item.collapse?'transform:rotate(90deg)':'transform:rotate(0deg)'}}" name="play" wx:if="{{item.children}}" bind:tap="showChildren" data-id="{{item.id}}"/>
<text class="{{item.selected?'current':''}}" data-id="{{item.id}}" bind:tap="handleClick">{{item.text}}</text>
</view>
<block wx:if="{{item.children&&item.collapse}}">
<tree class="tree" treeList="{{item.children}}" is-can-choose-parnent="{{isCanChooseParnent2}}" bind:handleClick="treeClick"></tree>
</block>
</view>
</view>
</view>
js文件
//树形单选组件
Component({
properties:{
treeListIndex: {// 默认为0,当前循环的第几层,用于tree样式展示
type: Number,
value: 0
},
treeList: Array,
isCanChooseParnent:false
},
data:{
key:Math.random(),
treeArr:[
{
id:1,
text:'一级',
collapse:true,
selected:false,
children:[
{
id:"1-1",
text:"二级-1",
},
{
id:"1-2",
text:"二级-2",
children:[
{
id:"1-2-1",
text:"2-三级-1"
}
]
},
]
}
],
isExec:false,
currentIndex:"",
currentItem:"",
isCanChooseParnent2:false
},
observers:{
'isCanChooseParnent':function(val){
this.setData({
isCanChooseParnent2:val
})
}
},
methods:{
showChildren(e){
let id = e.currentTarget.dataset.id
this.setData({
isExec:!this.data.isExec
})
let item = this.findCurrentItem(id,this.data.treeList,'collapse')
this.setData({
treeList:this.data.treeList
})
//点击icon
this.triggerEvent("handleClick",{item,'type':'icon'})
},
/**
* @t 功能类型 collapse:点击图标展开收起,title:点击标题事件
* */
findCurrentItem(id,list,t=''){
let item =""
list.forEach(it=>{
if(it.id==id){
if(t=='collapse'){
it.collapse = !it.collapse
}
if(t=="title"){
it.selected = !it.selected
}
item = it
}else{
if(t=="title"){
it.selected =false
}
if(it.children){
this.findCurrentItem(id,it.children,t)
}
}
})
return item
},
handleClick(e){
let id = e.currentTarget.dataset.id
let arrs = [...this.data.treeList]
let item =this.findCurrentItem(id,arrs,"title")
console.log(this.data.isCanChooseParnent2,3333333)
if(item?.children&&!this.data.isCanChooseParnent2){
wx.showToast({title:"不能选择父级节点",icon:'none'})
return
}
this.setData({
currentIndex:id,
treeList:arrs,
currentItem:item
})
wx.setStorageSync("tree-item",item)
this.triggerEvent("handleClick",{item})
},
//递归接收
treeClick(e){
let {item,type='val'} = e.detail
this.triggerEvent("handleClick",{item,type})
}
},
created(){
},
lifetimes:{
attached: function() {
this.data.treeArr = JSON.parse(JSON.stringify(this.data.treeList))
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
}
})
json文件
{
"usingComponents": {
"tree":"/dangerSourceIdentify/pages/treeSelect/index",
"van-icon": "@vant/weapp/icon/index"
}
}
wxss文件:
.tree-box {
background: white;
font-size: 34rpx;
}
.current {
/*color: blue;*/
}
.item-icon-text {
display:flex;
flex-direction: row;
justify-content: start;
align-items: center;
}
父组件:
json文件: