一百多行代码实现Tree树形组件,支持的props
和events
是参考elementUI
设置的,功能相对简单,支持配置如下:
Props
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|
data | 展示数据 | array | —— | —— |
showCheckbox | 是否可选择 | boolean | —— | false |
defaultExpandAll | 默认展开所有 | boolean | —— | true |
props | 配置项 | object | —— | —— |
Events
事件名 | 说明 | 回调参数 |
---|
node-click | 节点被点击的回调 | 该节点所对应的对象 |
组件代码
<template>
<ul class="tree">
<li class="tree-item" v-for="(item, index) in data" :key="item[props.key]">
<div class="node-item" @click="clickNodeItem($event, item, index)">
<i v-show="item[props.children]?.length" :class="{ down: expandStates[index] }" class="icon"
@click="changeExpandStatus(index)"></i>
<input v-if="showCheckbox" :disabled="item[props.disabled]" class="checkbox" type="checkbox">
<span class="label">{{ item[props.label] }}</span>
</div>
<template v-if="item[props.children]?.length">
<WuTree v-show="expandStates[index]" :data="item[props.children]" v-bind="$props" v-on="$listeners"></WuTree>
</template>
</li>
</ul>
</template>
<script>
export default {
name: 'WuTree',
props: {
data: {
type: Array,
default() {
return []
}
},
showCheckbox: {
type: Boolean,
default: false
},
defaultExpandAll: {
type: Boolean,
default() {
return false
}
},
props: {
type: Object,
default() {
return {
label: 'label',
children: 'children',
key: 'id',
disabled: 'disabled'
}
}
}
},
data() {
return {
expandStates: []
}
},
created() {
this.expandStates = this.data.map(() => this.defaultExpandAll)
},
methods: {
clickNodeItem(e, item, index) {
const classNames = ['icon', 'checkbox']
if (classNames.some(className => e.target.className.includes(className))) {
return
}
this.$emit('node-click', item)
if (item.children && item.children.length > 0) {
this.changeExpandStatus(index)
}
},
changeExpandStatus(index) {
this.$set(this.expandStates, index, !this.expandStates[index])
}
}
}
</script>
<style lang="scss" scoped>
.tree {
user-select: none;
.tree-item {
position: relative;
padding-left: 20px;
.node-item {
display: flex;
align-items: center;
cursor: pointer;
&:hover {
background-color: #f0f7ff;
}
.icon {
position: absolute;
left: 6px;
width: 0;
height: 0;
transform-origin: 0% 50%;
border: 6px solid transparent;
border-left-color: grey;
transition: all 0.1s;
&.down {
transform: rotate(90deg);
}
}
}
.checkbox {
margin-right: 5px;
&:disabled {
cursor: not-allowed;
}
}
}
}
</style>
使用
<template>
<div class="container">
<WuTree :data="treeData" :showCheckbox="true" :default-expand-all="true" @node-click="handleNodeClick"></WuTree>
</div>
</template>
<script>
import WuTree from '@/components/WuTree'
export default {
name: 'Home',
components: {
WuTree
},
data() {
return {
treeData: [
{
id: 1,
label: '一级 1',
disabled: true,
children: [{
id: 4,
label: '二级 1-1',
children: [{
id: 9,
label: '三级 1-1-1'
}, {
id: 10,
label: '三级 1-1-2'
}]
}]
},
{
id: 2,
label: '一级 2',
children: [{
id: 5,
label: '二级 2-1'
}, {
id: 6,
label: '二级 2-2'
}]
},
{
id: 3,
label: '一级 3',
children: [{
id: 7,
label: '二级 3-1'
}, {
id: 8,
label: '二级 3-2'
}]
}]
}
},
methods: {
handleNodeClick(e) {
console.log('点击节点', e)
}
}
}
</script>
<style lang="scss" scoped>
.container {
padding: 50px;
}
</style>
效果
