树状数组
<template>
<view class="content">
<view class="mix-tree-list">
<block v-for="(item, index) in treeList" :key="index">
<!-- <van-swipe-cell :right-width="155"> -->
<view
class="mix-tree-item"
:style="[{
paddingLeft: item.rank*15 + 'px',
zIndex: item.rank*-1 +50
}]"
:class="{
border: treeParams.border === true,
show: item.show,
last: item.lastRank,
showchild: item.showChild
}"
>
<view @click.stop="treeItemTap(item, index)">
<image class="mix-tree-icon" :src="item.lastRank ? treeParams.lastIcon : item.showChild ? treeParams.currentIcon : treeParams.defaultIcon"></image>
{{item.name}}
</view>
<view class="total-cell" v-if="allowUpdate=='允许'">
<view class="van-cell">
</view>
<view class="van-cell">
</view>
<view class="van-cell">
</view>
</view>
</view>
<!-- </van-swipe-cell> -->
</van-swipe-cell>
</block>
</view>
</view>
</template>
<script>
export default {
props: {
list: {
type: Array,
default(){
return [];
}
},
params: {
type: Object,
default(){
return {}
}
},
allowUpdate: {
type: String,
default: '不允许'
}
},
data() {
return {
treeList: [],
treeParams: {
defaultIcon: '/static/mix-tree/defaultIcon.png',
currentIcon: '/static/mix-tree/currentIcon.png',
lastIcon: '',
border: false
}
}
},
watch: {
list(list){
this.treeParams = Object.assign(this.treeParams, this.params);
console.log(this.treeParams, this.params);
this.renderTreeList(list);
}
},
methods: {
addTree(item){
console.log(item);
},
renderTreeList(list=[], rank=0, parentId=[]){
list.forEach(item=>{
this.treeList.push({
id: item.id,
name: item.name,
sortNum: item.sortNum,
children: item.children,
parentId,
rank,
showChild: false,
show: rank === 0
})
if(Array.isArray(item.children) && item.children.length > 0){
let parents = [...parentId];
parents.push(item.id);
this.renderTreeList(item.children, rank+1, parents);
}else{
this.treeList[this.treeList.length-1].lastRank = true;
}
})
},
treeItemTap(item){
let list = this.treeList;
let id = item.id;
if(item.lastRank === true){
this.$emit('treeItemClick', item);
return;
}
item.showChild = !item.showChild;
list.forEach(childItem=>{
if(item.showChild === false){
if(!childItem.parentId.includes(id)){
return;
}
if(childItem.lastRank !== true){
childItem.showChild = false;
}
childItem.show = false;
}else{
if(childItem.parentId[childItem.parentId.length-1] === id){
childItem.show = true;
}
}
})
}
}
}
</script>
<style>
.mix-tree-list{
display: flex;
flex-direction: column;
padding-left: 30upx;
}
.mix-tree-item{
display: flex;
align-items: center;
font-size: 30upx;
color: #333;
height: 0;
opacity: 0;
transition: .2s;
position: relative;
}
.mix-tree-item.border{
border-bottom: 1px solid #eee;
}
.mix-tree-item.show{
height: 80upx;
opacity: 1;
}
.mix-tree-icon{
width: 26upx;
height: 26upx;
margin-right: 8upx;
opacity: .9;
}
.mix-tree-item.showchild:before{
transform: rotate(90deg);
}
.mix-tree-item.last:before{
opacity: 0;
}
.total-cell{
display: flex;
}
.van-cell{
}
</style>
调用(包含父子关系数组转换成树状结构)
<template>
<view class="content">
<!-- 导航栏 -->
<!-- #ifdef APP-PLUS -->
<view style="padding-bottom: 60px;">
<van-nav-bar
title="个人信息"
left-text="返回"
left-arrow
:fixed="true"
z-index="999"
@click-left="$navigateBack(1)"
/>
</view>
<!-- #endif -->
<view class="topAdd">
<vant-btn type="info" size="small">添加主目录</vant-btn>
</view>
<mix-tree
:list="list"
:params="treeParams"
@treeItemClick="treeItemClick"
:allowUpdate="allowUpdate"
></mix-tree>
</view>
</template>
<script>
var that;
import mixTree from '@/components/mix-tree/mix-tree';
export default {
components: {
mixTree
},
props:["allowUpdate"],
data() {
return {
list: [],
treeParams: {
defaultIcon: '/static/i2.png',
currentIcon: '/static/i1.png',
lastIcon: '/static/i3.png',
border: true
}
}
},
methods: {
getSiteGroundPage(pageData) {
that.$showLoading();
var data = {
rows: 1000,
page: 0,
sortName: "sortNum",
sortOrder: "asc"
};
that.$http.post(that.webRoot.host+that.webRoot.siteGroundPage.getTotalGroup,
pageData || data,
{
headers:{
'content-type':that.webRoot.header.contentType,
'Authorization': 'bearer '+uni.getStorageSync('access_token'),
'deviceId' : that.UUID
},
}).catch(function(response){
uni.hideLoading();
console.log(response);
if(response.status==200){
that.list = that.getList(response.data.content);
console.log(that.list);
}else{
uni.showToast({
title: response.message,
icon:'none'
});
}
})
},
getList(data) {
let parents = data.filter(value => value.parentId == 'undefined' || value.parentId == null)
let children = data.filter(value => value.parentId !== 'undefined' && value.parentId != null)
let translator = (parents, children) => {
parents.forEach((parent) => {
children.forEach((current, index) => {
if (current.parentId === parent.id) {
let temp = JSON.parse(JSON.stringify(children))
temp.splice(index, 1)
translator([current], temp)
typeof parent.children !== 'undefined' ? parent.children.push(current) : parent.children = [current]
}
}
)
}
)
}
translator(parents, children)
return parents
},
treeItemClick(item) {
let {
id,
name,
parentId
} = item;
uni.showModal({
content: `点击了${parentId.length+1}级菜单, ${name}, id为${id}, 父id为${parentId.toString()}`
})
console.log(item)
}
},
created() {
that = this;
that.getSiteGroundPage();
},
}
</script>
<style lang="scss">
.content{
.topAdd{
padding: 2vh;
}
}
</style>
树状结构拆分成父子节点数组(用于展开与收缩,致谢-----庄哥)
<template>
<view>
<view v-for="(item, index) in list" :key="index" :style="{marginLeft: (item.level - 1) * 20 + 'rpx'}" class="list-item"
v-show="item.show" @tap="showChildren(index)">
{{item.name}}
</view>
</view>
</template>
<script>
export default {
components: {},
data() {
return {
dataList: [{
"addDate": 1551926856000,
"id": 36,
"name": "西藏",
"siteId": 80,
"sortNum": 2,
"updateDate": 1551926856000,
"children": [{
"addDate": 1579073689000,
"id": 942,
"name": "111",
"parentId": 36,
"siteId": 80,
"sortNum": 6,
"updateDate": 1579073689000,
"children": [{
"addDate": 1579137342000,
"id": 943,
"name": "22",
"parentId": 942,
"siteId": 80,
"sortNum": 7,
"updateDate": 1579137342000,
"text": "22"
}],
"text": "111"
}],
"text": "西藏"
}, {
"addDate": 1551926847000,
"id": 35,
"name": "张家界",
"siteId": 80,
"sortNum": 1,
"updateDate": 1551926847000,
"children": [{
"addDate": 1584589492000,
"id": 945,
"name": "天门山",
"parentId": 35,
"siteId": 80,
"sortNum": 8,
"updateDate": 1584589492000,
"children": [{
"addDate": 1584589522000,
"id": 946,
"name": "玻璃桥",
"parentId": 945,
"siteId": 80,
"sortNum": 9,
"updateDate": 1584589522000,
"children": [{
"addDate": 1584589528000,
"id": 947,
"name": "安全组",
"parentId": 946,
"siteId": 80,
"sortNum": 10,
"updateDate": 1584589528000,
"text": "12"
}],
"text": "12"
}],
"text": "42"
}],
"text": "张家界"
}, {
"addDate": 1551926847000,
"id": 35,
"name": "苏州",
"siteId": 80,
"sortNum": 1,
"updateDate": 1551926847000,
}],
list: [],
}
},
onLoad() {
var list = [];
try {
this.getList(this.dataList, 1);
} catch (err) {
console.log(err)
}
},
methods: {
getList(data, level) {
for (let d_item of data) {
const item = {
id: d_item.id,
name: d_item.name,
parentId: d_item.parentId,
show: level === 1,
level,
counts: d_item.children ? d_item.children.length : 0,
}
this.list.push(item);
if (d_item.children && d_item.children.length > 0) {
this.getList(d_item.children, level + 1);
}
}
},
showChildren(ind) {
let {
list
} = this;
if (list[ind].counts === 0) return;
for (let i = ind + 1; i < list.length; i++) {
if (list[i].show) {
if (list[i].level > list[ind].level) {
list[i].show = false;
}
} else {
if (list[i].level === list[ind].level + 1) {
list[i].show = true;
}
}
if (list[i].level <= list[ind].level) {
break;
}
}
this.list = list;
}
},
}
</script>
<style>
.list-item {
padding: 20rpx 0;
}
</style>