android树形结构单选,小程序树形组件单选实现

树形组件,常规思想是递归实现,主要是不知道有多少层。在react中,支持jsx写法,即HTML中加入js代码,就可以使用函数递归来生成树,而小程序里面的写法,我现在还没搞太懂,个人感觉不支持。就使用组件递归来生成树,即在组件中调用自身。

WXML代码

{{item.title}}

js代码:

const tranverse=(e)=>{

for(let i in e){

if (e[i].children) {

e[i].open = false;

tranverse(e[i].children)

}

e[i].selected=false;

}

}

Component({

properties:{

treeList:{

type:Array,

value: [{

title: 'Node1',

id:0,

children: [

{

title: 'Child Node1',

id:2,

children:[{

title:'grandChild Node1',

id:4

}]

},

{

title: 'Child Node2',

id:3

},

],

},

{

title: 'Node2',

id:1

},

]},

depth:{

type:Number,

value:0

}

},

data:{

},

ready(){

const {treeList}=this.properties;

for(let i in treeList){

if(treeList[i].children){

treeList[i].open=false;

tranverse(treeList[i].children);

}

treeList[i].selected=false;

}

this.setData({

tree:treeList

})

},

methods:{

onchange(e){

const {treeList}=this.data;

const {id}=e.currentTarget.dataset;

this.changeOpen(treeList,id);

this.triggerEvent('change',id,{bubbles:true,composed:true});

this.setData({

tree:treeList

})

},

//修改折叠状态

changeOpen(tree,id){

for(let i=0;i

if(tree[i].id===id){

tree[i].open=!tree[i].open;

}

if(tree[i].children){

this.changeOpen(tree[i].children,id);

}

}

return;

},

change(e){

const id = e.detail;

const { treeList } = this.data;

this.changeOpen(treeList, id);

this.setData({

tree: treeList

})

},

click(e){

const t = this.selectAllComponents('#treeSelect');

t.forEach(item => {

item.click(e);

})

let id='';

if(e.detail){

id = e.detail.id;

}

const { treeList } = this.data;

this.setStatus(treeList, id);

this.setData({

tree: treeList

})

},

handleClick(e){

const t = this.selectAllComponents('#treeSelect');

t.forEach(item => {

item.click(e);

})

const {id}=e.currentTarget.dataset;

const {treeList}=this.data;

const value = this.getData(treeList,id)

this.setStatus(treeList,id);

this.triggerEvent('onclick',{id,value},{composed:true,bubbles:true});

this.setData({

tree:treeList

})

},

//切换选中状态

setStatus(tree,id){

for(let i=0;i

if(tree[i].id==id){

tree[i].selected=true;

}else{

tree[i].selected=false;

}

if (tree[i].children) {

this.setStatus(tree[i].children, id);

}

}

return ;

},

//获取选中项信息

getData(tree, id) {

for (let i = 0; i < tree.length; i += 1) {

if (tree[i].id === id) {

return tree[i].title;

}

if (tree[i].children) {

this.getData(tree[i].children, id);

}

}

return '';

},

}

})

调用时:

js代码:

lclick(e) {

const t = this.selectAllComponents('#treeSelect');

t.forEach(item => {

item.click(e);

})

const {id,value} = e.detail;

const { pageData } = this.data;

if(pageData){

this.setStatus(pageData, id);

}

this.setData({

tree: pageData,

choose:{id,value}

})

},

setStatus(tree, id) {

for (let i = 0; i < tree.length; i += 1) {

if (tree[i].id == id) {

tree[i].selected = true;

} else {

tree[i].selected = false;

}

if (tree[i].children) {

this.setStatus(tree[i].children, id);

}

}

return;

},

后续将继续优化

代码讲解:

上半部分就是渲染本层的树节点,其中包含对是否是父节点的判断,父节点前会加一个展开/关闭图标,若有子节点,就调用自身渲染本层节点,depth主要用来做缩进,每加一层,后面的树就会向后移动。

接下来就是重头戏,单选是怎样实现的。首先,当选中某一节点时,会拿到对应节点的id,然后拿着id去遍历该层数据将对应id的节点的selected设为true,其余设为false,并向下传递,同样更改下层的节点为false,关键到了,怎么修改更高层的状态呢,通过this.triggerEvent()将id传到高层节点,做同样的操作,配置triggerEvent时需配置{ bubbles: true, composed: true },允许冒泡,否则数据传不到上层。然后就可以实现单选了。具体见代码。我已经说不清了,就这样吧。

组件递归很简单,也很实用。但现实是残酷的,我需要实现单选功能,本来想的很简单,通过回调将选中项的selected属性设为true,其余项的selected属性设为false即可,但是事实是由于是递归生成的,每一层之间没有关联,每层的treelist只是根节点的一部分,就会有一个问题是每一层可以实现单选,但是并不满足条件。只能另想办法。

思路很简单,但点击某个节点时,一方面向下传递,将下级的节点的selected设为false,另一方面向上传递,将父节点的其余节点selected设为false,实现整体的统一,即实现单选。具体详见代码。

其实还想过用小程序的模板即template,这样就能很容易实现单选,但是小程序不允许用template递归,就只能放弃了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值