vue 实现树形结构

我们先写个tree组件 递归组件

tree.vue文件

<template>

<ul class="ul-wrapper">

<!-- 包裹层-->

<li v-for="item in list" :key="item.key">

<!-- 遍历-->

<div>

<!-- 是否展开图标-->

<img class="icon" v-show="item.children" @click="changeShow" />

<!-- CheckBox-->

<!-- <input type="checkbox" :name="item.key" @click="clickbox" :checked="isChecked(item.key)" :disabled="item.disabled" /> -->

<div class="checkbox-title">{{ item.title }}</div>

<!-- CheckBox内容-->

</div>

<tree v-if="showChildren" :list="item.children"></tree>

<!-- 遍历children-->

</li>

</ul>

</template>

<script type="text/ecmascript-6">

export default {

name: 'tree',

props: {

list: { // 所有树节点

type: Array,

default: () => {

return []

}

}

},

data () {

return {

showChildren: true // 是否展开根目录

}

},

computed: { // computed属性计算展开图标

imgUrl () {

return this.showChildren ? 'down.png' : 'right.png'

}

},

methods: {

clickbox (e) { // 点击CheckBox时需要加入或删除已选中this.$global.nodes的节点数组中

const checked = e.target.checked

const key = e.target.name

const nodes = this.$global.nodes // this.$global.nodes是全局变量,便于递归组件记录选中节点

if (checked) {

if (!nodes.includes(key)) {

this.$global.nodes.push(key)

}

} else {

this.$global.nodes = nodes.filter((item) => {

return key !== item

})

}

},

changeShow () { // 点击是否展开根目录,当前状态取反即可

this.showChildren = !this.showChildren

},

isChecked (key) { // 查看是否已经存在于选中节点中

return this.$global.nodes.includes(key)

}

}

}

</script>

<style >

.ul-wrapper

margin 10px 30px 0

.checkbox-title, .icon

display inline-block

vertical-align middle

.icon

margin-left -20px

height 18px

width 18px

input[type="checkbox"]

position relative

display inline-block

vertical-align middle

padding 0

margin-right 5px

height 18px

width 18px

border 1px solid #ccc

border-radius 3px

input[type="checkbox"]:checked::before

position absolute

top 0

left 0

padding-left 2px

content: "\2713";

height 15px

width 13px

font-size 12px

font-weight: bold;

background #1296db

color #fff

border-radius 3px

border 0

input[type="checkbox"]:disabled::before // CheckBox禁用状态时样式修改

position absolute

top 0

left 0

padding-left 2px

content: "";

height 15px

width 13px

font-size 12px

font-weight: bold;

background #ccc

color #fff

border-radius 3px

border 0

</style>

home.vue 引入tree组件

<template>

<Tree :list="treeData"></Tree>

</template>

<script >

import { defineComponent } from 'vue'

import Tree from '@/components/tree.vue'

export default defineComponent({

name: 'home',

components: {

Tree

},

setup() {

const treeData = [

{

title: '1',

key: '1',

children: [

{

title: '1-1',

key: '1-1',

children: [

{ title: '1-1-1', key: '1-1-1' },

{ title: '1-1-2', key: '1-1-2' },

{ title: '1-1-3', key: '1-1-3' }

]

},

{

title: '1-2',

key: '1-2',

children: [

{ title: '1-2-1', key: '1-2-1' },

{ title: '1-2-2', key: '1-2-2' },

{ title: '1-2-3', key: '1-2-3' }

]

},

{

title: '1-3',

key: '1-3'

}

]

},

{

title: '2',

key: '2',

disabled: 'true',

children: [

{ title: '2-1', key: '2-1' },

{ title: '2-2', key: '2-2' },

{ title: '2-3', key: '2-3' }

]

},

{

title: '3',

key: '3'

}

]

return {

treeData

}

}

})

</script>