1.安装
npm i vue2-org-tree
npm install -D less-loader less
安装 less-loader出错解决办法,直接在package.json=》devDependencies下面加入less和less-loader版本,然后执行npm i
,我用的nodejs版本是 16.18.0,“webpack”: “^4.47.0”
2.demo
<template>
<div ref="appContainer" class="app-container">
<div style="margin-left:30px;">
<el-row :gutter="20">
<el-col :span="5">
<el-switch v-model="horizontal" :width="50" active-text="横排" inactive-text="竖排" style="margin-top:8px;"/>
</el-col>
</el-row>
</div>
<div style="font-size:12px;margin-top:30px;">
<vue2-org-tree
:data="treeData"
:horizontal="!horizontal"
collapsable
:render-content="renderContent"
@on-expand="onExpand"
@on-node-click="NodeClick"/>
</div>
</div>
</template>
<script>
export default {
name: "TreeTest",
data() {
return {
horizontal:true,
treeData: {
id: '0',
label: "NBA季后赛",
children: [
{
id: '1',
label: "西部球队",
children: [
{
id: '1-1',
label: "勇士"
},
{
id: '1-2',
label: "火箭"
},
{
id: '1-3',
label: "太阳"
},
{
id: '1-4',
label: "小牛"
}
]
},
{
id: '2',
label: "东部球队",
children: [
{
id: '2-1',
label: "热火"
},
{
id: '2-2',
label: "雄鹿"
},
{
id: '2-3',
label: "骑士"
},
{
id: '2-4',
label: "凯尔特人"
}
]
}
]
}
}
},
created() {
this.toggleExpand(this.treeData, true);
},
methods: {
collapse(list) {
list.forEach((child) => {
if (child.expand) {
child.expand = false;
}
child.children && this.collapse(child.children);
});
},
onExpand(e, data) {
console.log(data, 'data')
if ("expand" in data) {
data.expand = !data.expand;
if (!data.expand && data.children) {
this.collapse(data.children);
}
} else {
this.$set(data, "expand", true);
}
},
toggleExpand(data, val) {
if (Array.isArray(data)) {
data.forEach((item) => {
this.$set(item, "expand", val);
if (item.children) {
this.toggleExpand(item.children, val);
}
});
} else {
this.$set(data, "expand", val);
if (data.children) {
this.toggleExpand(data.children, val);
}
}
},
NodeClick(e, data) {
console.log(e)
// e 为 event
console.log(data)
// 当前项的所有详情 如:id label children
},
renderContent(h, data) {
return (
<div class="treeItem">{data.label}</div>
)
},
}
}
</script>
<style lang="less">
.org-tree-container {
display: inline-block;
padding: 15px;
background-color: #fff;
}
.org-tree {
// display: inline-block;
display: table;
text-align: center;
&:before, &:after {
content: '';
display: table;
}
&:after {
clear: both;
}
}
.org-tree-node,
.org-tree-node-children {
position: relative;
margin: 0;
padding: 0;
list-style-type: none;
&:before, &:after {
transition: all .35s;
}
}
.org-tree-node-label {
position: relative;
display: inline-block;
.org-tree-node-label-inner {
padding: 10px 15px;
text-align: center;
border-radius: 3px;
box-shadow: 0 1px 5px rgba(0, 0, 0, .15);
}
}
.org-tree-node-btn {
position: absolute;
top: 100%;
left: 50%;
width: 20px;
height: 20px;
z-index: 10;
margin-left: -11px;
margin-top: 9px;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 50%;
box-shadow: 0 0 2px rgba(0, 0, 0, .15);
cursor: pointer;
transition: all .35s ease;
&:hover {
background-color: #e7e8e9;
transform: scale(1.15);
}
&:before, &:after {
content: '';
position: absolute;
}
&:before {
top: 50%;
left: 4px;
right: 4px;
height: 0;
border-top: 1px solid #ccc;
}
&:after {
top: 4px;
left: 50%;
bottom: 4px;
width: 0;
border-left: 1px solid #ccc;
}
&.expanded:after {
border: none;
}
}
.org-tree-node {
padding-top: 20px;
display: table-cell;
vertical-align: top;
&.is-leaf, &.collapsed {
padding-left: 10px;
padding-right: 10px;
}
&:before, &:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 19px;
}
&:after {
left: 50%;
border-left: 1px solid #ddd;
}
&:not(:first-child):before,
&:not(:last-child):after {
border-top: 1px solid #ddd;
}
}
.collapsable .org-tree-node.collapsed {
padding-bottom: 30px;
.org-tree-node-label:after {
content: '';
position: absolute;
top: 100%;
left: 0;
width: 50%;
height: 20px;
border-right: 1px solid #ddd;
}
}
.org-tree > .org-tree-node {
padding-top: 0;
&:after {
border-left: 0;
}
}
.org-tree-node-children {
padding-top: 20px;
display: table;
&:before {
content: '';
position: absolute;
top: 0;
left: 50%;
width: 0;
height: 20px;
border-left: 1px solid #ddd;
}
&:after {
content: '';
display: table;
clear: both;
}
}
.horizontal {
.org-tree-node {
// display: flex;
// flex-direction: row;
// justify-content: flex-start;
// align-items: center;
display: table-cell;
float: none;
padding-top: 0;
padding-left: 20px;
&.is-leaf, &.collapsed {
padding-top: 10px;
padding-bottom: 10px;
}
&:before, &:after {
width: 19px;
height: 50%;
}
&:after {
top: 50%;
left: 0;
border-left: 0;
}
&:only-child:before {
top: 1px;
border-bottom: 1px solid #ddd;
}
&:not(:first-child):before,
&:not(:last-child):after {
border-top: 0;
border-left: 1px solid #ddd;
}
&:not(:only-child):after {
border-top: 1px solid #ddd;
}
.org-tree-node-inner {
display: table;
}
}
.org-tree-node-label {
display: table-cell;
vertical-align: middle;
}
&.collapsable .org-tree-node.collapsed {
padding-right: 30px;
.org-tree-node-label:after {
top: 0;
left: 100%;
width: 20px;
height: 50%;
border-right: 0;
border-bottom: 1px solid #ddd;
}
}
.org-tree-node-btn {
top: 50%;
left: 100%;
margin-top: -11px;
margin-left: 9px;
}
& > .org-tree-node:only-child:before {
border-bottom: 0;
}
.org-tree-node-children {
// display: flex;
// flex-direction: column;
// justify-content: center;
// align-items: flex-start;
display: table-cell;
padding-top: 0;
padding-left: 20px;
&:before {
top: 50%;
left: 0;
width: 20px;
height: 0;
border-left: 0;
border-top: 1px solid #ddd;
}
&:after {
display: none;
}
& > .org-tree-node {
display: block;
}
}
}
</style>
3.效果
参考:
https://www.cnblogs.com/liliuyu/p/17534861.html
https://blog.csdn.net/LlanyW/article/details/127647395
https://blog.csdn.net/qq_36437172/article/details/133900466