|
@@ -0,0 +1,96 @@
|
|
|
+<template>
|
|
|
+ <div class="custom-tree">
|
|
|
+ <div v-for="item in nodeData" :key="item.value" class="custom-tree-children">
|
|
|
+ <div class="custom-tree-item" @click.stop="toCurrentNode(item)">
|
|
|
+ <!-- 没有子节点数据不显示箭头 -->
|
|
|
+ <template v-if="item.children && item.children.length > 0">
|
|
|
+ <span v-if="!expandedkeysArray.includes(item.value)">→</span>
|
|
|
+ <span v-else>↓</span>
|
|
|
+ </template>
|
|
|
+ <span>{{ item.label }}</span>
|
|
|
+ </div>
|
|
|
+ <!-- children有值 && expandedkeysArray数组存在该value值时再展开显示 -->
|
|
|
+ <transition name="expand">
|
|
|
+ <custom-tree v-if="item.children && item.children.length > 0 && expandedkeysArray.includes(item.value)" :node-data="item.children" :style="{marginLeft: `${getLevel() * 20}px`}" />
|
|
|
+ </transition>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ name: 'custom-tree',
|
|
|
+ props: {
|
|
|
+ nodeData: {
|
|
|
+ type: Array,
|
|
|
+ default: () => ([])
|
|
|
+ },
|
|
|
+ expandedkeys: {
|
|
|
+ type: Array,
|
|
|
+ default: () => ([])
|
|
|
+ },
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ // 实时更新父组件的值
|
|
|
+ expandedkeysArray: {
|
|
|
+ get() {
|
|
|
+ return this.expandedkeys
|
|
|
+ },
|
|
|
+ set(newVal) {
|
|
|
+ this.$emit('update:expandedkeys', newVal)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 点击整行事件,向父组件返回当前节点和当前层级
|
|
|
+ toCurrentNode(item) {
|
|
|
+ const node = {
|
|
|
+ ...item,
|
|
|
+ level: this.getLevel()
|
|
|
+ }
|
|
|
+ this.$emit('currentNode', node)
|
|
|
+ // 没有展开的子节点才push展开
|
|
|
+ if (!this.expandedkeysArray.includes(item.value)) {
|
|
|
+ this.expandedkeysArray.push(item.value)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 已经展开的子节点删除收起
|
|
|
+ const index = this.expandedkeysArray.indexOf(item.value)
|
|
|
+ if (index !== -1) {
|
|
|
+ this.expandedkeysArray.splice(index, 1)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 根据父节点层数判断当前层级
|
|
|
+ getLevel() {
|
|
|
+ let level = 1;
|
|
|
+ let parent = this.$parent;
|
|
|
+ while (parent && parent.$options.name === 'custom-tree') {
|
|
|
+ level++;
|
|
|
+ parent = parent.$parent;
|
|
|
+ }
|
|
|
+ return level;
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style lang="less" scoped>
|
|
|
+.custom-tree{
|
|
|
+ .custom-tree-item{
|
|
|
+ cursor: pointer;
|
|
|
+ border-bottom: 1px solid #E4E7ED;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 5px 10px;
|
|
|
+ &:hover{
|
|
|
+ background: #F2F6FC;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.expand-enter-active, .expand-leave-active {
|
|
|
+ transition: all 0.3s;
|
|
|
+}
|
|
|
+.expand-enter, .expand-leave-to {
|
|
|
+ transform: scaleY(0);
|
|
|
+ transform-origin: top;
|
|
|
+ opacity: 0;
|
|
|
+}
|
|
|
+</style>
|