<template>
<div class="ui-xtree flex flex-col cannotselect">
<div class="item border-radius-ms flex flex-row flex-center-cz padding-left-l pointer"
:style="{paddingLeft: data.level * 15 + 'px'}"
:data-level="data.level"
:data-id="data.id"
:data-name="data.name">
<div class="flex flex-center-cz" @click="expand">
<img v-if="hasChild && !open" class="logo-20" src="@/assets/images/add.png"/>
<img v-if="hasChild && open" class="logo-20" src="@/assets/images/dec.png"/>
<div v-if="!hasChild" class="logo-20 show"></div>
</div>
<div class="flex flex-center-cz">
<input :value="data.id" @change="change(data.id)" v-model="checked" class="checkbox" type="checkbox"/>
</div>
<div class="font-s flex flex-center-cz">{{data.name}}</div>
</div>
<div v-show="open" v-if="hasChild">
<x-tree v-for="(item, index) in data.children" :data="item" :key="index" :root="root" ></x-tree>
</div>
</div>
</template>
<script>
export default {
name: 'XTree',
props: {
data: {},
root: {}
},
watch:{
data: {
handler(newValue) {
this.checked = newValue.checked
},
immediate: true,
deep: true //深度监听
}
},
data() {
return {
select: false,
open: false,
checked:null
}
},
computed: {
hasChild() {
return this.data.children && this.data.children.length //判断当前子组件有没有数据
}
},
methods: {
expand(event) {
if(this.hasChild) {
this.open = !this.open
}
event.stopPropagation();
},
change(id) {
this.root.change(id, this.checked);
}
}
}
</script>
<template>
<div class="full-height flex flex-col border scroll padding-l">
<div v-for="item in treeData" >
<x-tree :data="item" :root="root"></x-tree>
</div>
</div>
</template>
<script>
import XTree from '@/components/xTree/XTree'
export default {
name: 'XTreeView',
props:{
treeData:{}
},
components: {
XTree
},
data() {
return {
root: this,
}
},
methods: {
change(id, value) {
var find = this.getItem(this.treeData, id);
console.log("find",find)
if (find != null) {
find.checked = value;
if (find.children && find.children != null && find.children.length > 0) {
this.updateAll(find.children, value);
}
}
},
getItem(data, id) {
console.log("id", id)
console.log("len",data.length);
for (var i= 0; i< data.length; i++) {
console.log("data", data)
var item = data[i];
if (item.id == id) {
return item ;
} else {
if (item.children && item.children != null && item.children.length > 0) {
let result = this.getItem(item.children, id);
if (result != null) {
return result;
}
}
}
}
},
updateAll(children, value) {
children.forEach(item => {
item.checked = value;
if (item.children && item.children != null && item.children.length > 0) {
this.updateAll(item.children, value);
}
});
}
}
}
</script>
<template>
<div class="body">
<div class="table">
<div class="filter font-bold">组件库(六) 多选树形组件</div>
<div class="flex flex-col margin-top-l margin-left-l" style="height:250px;width:350px;">
<x-tree-view :treeData="treeData" :root="root" @change="change"></x-tree-view>
</div>
<div class="margin-top-xl margin-left-l btn-blue-auto pointer" style="width:350px;" @click="confirm">确定</div>
<div class="padding-xl">选中的数据为:{{this.treeData}}</div>
</div>
</div>
</template>
<script>
/*
名称:组件库(六) 多选树形组件
功能:vue树形结构,支持多选、不限层级,子组件调用父组件方法,遍历DOM操作
作者:唐赢
时间:2023-1-14
*/
import XTreeView from '@/components/xTree/XTreeView'
export default {
name: 'XTreeDemo',
components: {
XTreeView
},
data () {
return {
treeData : [
{
"id":1,
"name": "业务管理",
"level": 1,
"checked": true,
children: [
{ "id":2,
"name": "采购订单",
"level": 2,
"checked": true,
},
{ "id":3,
"name": "销售订单",
"level": 2,
"checked": true,
}
],
},
{
"id":4,
"name": "系统管理",
"level": 1,
"checked": true,
children: [
{ "id":5,
"name": "权限管理",
"level": 2,
"checked": true,
children: [
{ "id": 7,
"name": "用户管理",
"level": 3,
"checked": true,
},
{ "id": 8,
"name": "角色管理",
"level": 3,
"checked": true,
}
]
},
{ "id":6,
"name": "数据字典",
"level": 2,
"checked": true,
}
]
}
],
root: this,
}
},
methods: {
change(data) {
this.treeData = data;
},
confirm() {
console.log(this.treeData);
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.body {
display: flex;
justify-content: center;
margin-top: 73px;
width: 100%;
}
.table {
background-color: #fff;
width: 1080px;
min-height: 800px;
box-shadow: 0px 3px 6px rgba(0, 0, 0, .1);
margin-bottom: 10px;
}
.filter {
display: flex;
height: 60px;
align-items:center;
background-color: #fff;
font-size: 18px;
justify-content: center;
border-bottom: 1px solid rgba(0, 0, 0, .2);;
}
</style>