官方文档解析
前提了解:
1,@dblclick是双击
2,递归使用树形组件的时候,js逻辑相当于有重新走一遍。
源码
主代码 treeView1.vue
<template>
<ul id="demo">
<tree1
class="item"
:model="treeData">
</tree1>
</ul>
</template>
<script>
import tree1 from '../common/tree1'
export default {
name: "tree-view1",
components: {
tree1
},
data(){
return{
treeData:{
name: 'My Tree',
children: [
{ name: 'hello' },
{ name: 'wat' },
{
name: 'child folder',
children: [
{
name: 'child folder',
children: [
{ name: 'hello' },
{ name: 'wat' }
]
},
{ name: 'hello' },
{ name: 'wat' },
{
name: 'child folder',
children: [
{ name: 'hello' },
{ name: 'wat' }
]
}
]
}
]
}
}
},
mounted(){
},
computed:{
},
methods:{
}
}
</script>
<style scoped>
body {
font-family: Menlo, Consolas, monospace;
color: #444;
}
.item {
cursor: pointer;
}
.bold {
font-weight: bold;
}
ul {
padding-left: 1em;
line-height: 1.5em;
list-style-type: dot;
}
</style>
树形组件代码 tree1.vue
<template>
<li>
<!--@dblclick="changeType" 双击变成文件夹-->
<div
:class="isFolder?'bold':''"
@click="toggle"
@dblclick="changeType"
>
{{ model.name }}
<!--是文件夹的话 有span 和 ul-->
<span v-if="isFolder">---open:{{open}}[{{ open ? '-' : '+' }}]</span>
</div>
<!--非0 都是true
v-show,v-if只要都为true才能显示
-->
<ul v-show="open" v-if="isFolder">
<!--再次进来tree1的时候相当于有重新走了一边tree1组件 open默认为false-->
<tree1
class="item"
v-for="(model, index) in model.children"
:key="index"
:model="model">
</tree1>
<li class="add" @click="addChild">+</li>
</ul>
</li>
</template>
<script>
export default {
name: "tree1",
data(){
return{
open: false,
}
},
props:{
model:{type:Object},
},
mounted(){
},
computed:{
isFolder: function () {
return this.model.children &&
this.model.children.length
}
},
methods:{
toggle: function () {
if (this.isFolder) {
this.open = !this.open
}
console.log(this.isFolder)
console.log(this.open)
},
changeType: function () {//双击的时候会触发点击事件 所以创建children数组的时候直接
if (!this.isFolder) {
// Vue.set(this.model, 'children', [])
this.$set(this.model, 'children', [])
this.addChild();
this.open = true
}
},
addChild: function () {
this.model.children.push({
name: 'new stuff'
})
}
}
}
</script>
<style scoped>
</style>
常用场景
源码
主代码 treeView.vue
<template>
<div class="div_tree">
<div>
<my-tree :data="theData" :name="menuName"></my-tree>
</div>
</div>
</template>
<script>
const myData = [
{
id: '1',
menuName: '基础管理',
menuCode: '10',
children: [
{
menuName: '用户管理',
menuCode: '11'
},
{
id: '12',
menuName: '角色管理',
menuCode: '12',
children: [
{
menuName: '管理员',
menuCode: '121'
},
{
menuName: 'CEO',
menuCode: '122'
},
{
menuName: 'CFO',
menuCode: '123'
},
{
menuName: 'COO',
menuCode: '124'
},
{
menuName: '普通人',
menuCode: '124'
}
]
},
{
menuName: '权限管理',
menuCode: '13'
}
]
},
{
id: '2',
menuName: '商品管理',
menuCode: '',
children: [
{
menuName: '商品一',
menuCode: '21'
},
{
id: '22',
menuName: '商品二',
menuCode: '22',
children: [
{
menuName: '子类商品1',
menuCode: '221'
},
{
menuName: '子类商品2',
menuCode: '222'
}
]
}
]
},
{
id: '3',
menuName: '订单管理',
menuCode: '30',
children: [
{
menuName: '订单列表',
menuCode: '31'
},
{
menuName: '退货列表',
menuCode: '32',
children: []
}
]
},
{
id: '4',
menuName: '商家管理',
menuCode: '',
}
];
import myTree from '../common/tree.vue'
export default {
components: {
myTree
},
data () {
return {
theData: myData,
menuName: 'menuName', // 显示菜单名称的属性
}
},
methods: {
}
}
</script>
<style scoped>
</style>
树形组件代码 tree.vue
<template>
<ul class="tree-menu">
<li v-for="(item, index) in data">
<span @click="toggle(item, index)">
<i :class="['icon', item.children && item.children.length ? folderIconList[index] : 'file-text',]"></i>
{{ item[name] || item.menuName }}
</span>
<tree-menu v-if="scope[index]" :data="item.children"></tree-menu>
</li>
</ul>
</template>
<script>
export default {
name: 'treeMenu',//必须命名 自己使用
props: {
data: Array,
name: String,
},
data () {
return {
folderIconList: [],
scope: {}
}
},
created () {
this.data.forEach((item, index) => {
// console.log(index)
// console.log(item)
if (item.children && item.children.length) {
this.folderIconList[index] = 'folder';//0,1,2 是文件夹
}
});
},
methods: {
doTask (index) {
this.$set(this.scope, index, !this.scope[index]);
console.log(this.scope)
this.folderIconList[index] = this.scope[index] ? 'folder-open' : 'folder'; //判断文件夹是否为打开状态
},
toggle (item, index) {
console.log(index);
console.log(item)
if (item.children && item.children.length) {
this.doTask(index);
} else {
}
}
}
}
</script>
<style scoped>
.tree-menu {
list-style: none;
}
.tree-menu li {
line-height: 2;
}
.tree-menu li span {
cursor: default;
}
.icon {
display: inline-block;
width: 15px;
height: 15px;
background-repeat: no-repeat;
vertical-align: -2px;
}
.icon.folder {
background-image: url(../../src/assets/folder.png);
}
.icon.folder-open {
background-image: url(../../src/assets/folder-open.png);
}
.icon.file-text {
background-image: url(../../src/assets/file-text-o.png);
}
.icon.loading {
background-image: url(../../src/assets/loading.png);
background-size: 15px;
}
</style>
主要讲的就是递归