123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- <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>
|