通过递归实现多级菜单

 因为elementUI的菜单组件不能实现祖级以及父级的点中效果,只能点到最后一级别,所以自己写了一个简UI的DEMO【代码可以直接使用】

1、异步组件实现递归

2、展开和收起效果和element一致

3、对比饿了吗,此DEMO每一级别均可点击,且可以自动滚动到菜单的位置

<style scoped>
  aside {
    width: 200px;
    height: 300px;
    overflow: auto;
  }
</style>

<template>
  <div class="home">
    <aside>
      <tab-list
        v-bind:active="active"
        v-bind:list="data"
        v-on:tabClick="tabClickHandler"
      />
    </aside>
  </div>
</template>

<script>
  import TabList from '@/components/TabList'
  export default {
    name: 'Home',
    data () {
      return {
        active: '7',
        data: [
          {
            id: '1',
            name: '一级',
            children: [
              {
                id: '1-1',
                name: '二级',
                children: [
                  {
                    id: '1-1-1',
                    name: '三级',
                    children: []
                  }
                ]
              },
              {
                id: '1-2',
                name: '二级',
                children: []
              }
            ]
          },
          {
            id: '2',
            name: '一级2',
            children: [
              {
                id: '2-2',
                name: '二级2',
                children: [
                  {
                    id: '2-2-2',
                    name: '三级2',
                    children: []
                  }
                ]
              }
            ]
          },
          {
            id: '4',
            name: '一级',
            children: []
          },
          {
            id: '5',
            name: '一级',
            children: []
          },
          {
            id: '6',
            name: '一级',
            children: []
          },
          {
            id: '7',
            name: '一级',
            children: []
          },
          {
            id: '8',
            name: '一级',
            children: []
          },
          {
            id: '9',
            name: '一级',
            children: []
          },
          {
            id: '10',
            name: '一级',
            children: []
          }
        ]
      }
    },
    methods: {
      tabClickHandler (item) {
        this.active = item.id
      }
    },
    components: {
      [TabList.name]: TabList
    }
  }
</script>
<style scoped>
  ul {
    margin: 0;
    padding: 0 0 0 20px;
  }
</style>

<template>
  <ul class="tab-list">
    <tab-item
      v-for="item in list"
      v-bind:item="item"
      v-bind:active="active"
      v-bind:key="item.id"
      v-on:tabClick="tabClick"
    />
  </ul>
</template>

<script>
  import TabItem from './TabItem.vue'
  export default {
    name: 'TabList',
    props: {
      list: {
        type: Array,
        default: []
      },
      active: {
        type: String,
        default: ''
      }
    },
    methods: {
      tabClick (item) {
        this.$emit('tabClick', item)
      }
    },
    components: {
      [TabItem.name]: TabItem
    }
  }
</script>

 

<style scoped>
  li {
    list-style: none;
  }
  section {
    line-height: 50px;
    cursor: pointer;
  }
  section:hover {
    background-color: #409eff;
  }
  section.active {
    color: #409eff;
    background-color: inherit;
  }
  .tab-list {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.25s;
  }
  .tab-list.open {
    max-height: 999px;
  }
</style>

<template>
  <li class="tab-item">
    <section
      v-bind:class="{active: active === item.id}"
      v-on:click="tabItemClick(item)"
    >
      <span>{{ item.name }}</span>
      <i v-if="item.children.length">
        {{ toggle ? '折叠' : '展开' }}
      </i>
    </section>
    <tab-list
      v-if="item.children.length"
      v-bind:class="{ open: toggle }"
      v-bind:list="item.children"
      v-bind:active="active"
      v-on:tabClick="tabClick"
    />
  </li>
</template>

<script>
  function findChildren (list, id) {
    for (let i = 0; i < list.length; i++) {
      let item = list[i]
      if (item.id === id) {
        return item
      } else {
        let result = findChildren(item.children, id)
        if (result) {
          return result
        }
      }
    }
  }
  export default {
    name: 'TabItem',
    props: {
      item: {
        type: Object,
        default: {
          id: '',
          name: '',
          children: []
        }
      },
      active: {
        type: String,
        default: ''
      }
    },
    data () {
      return {
        toggle: false
      }
    },
    created () {
      this.toggle = !!findChildren(this.item.children, this.active)
    },
    mounted () {
      if (this.item.id === this.active) {
        this.$el.scrollIntoView({ behavior: 'smooth', block: 'center' })
      }
    },
    methods: {
      tabItemClick (item) {
        this.toggle = !this.toggle
        this.tabClick(item)
      },
      tabClick (item) {
        this.$emit('tabClick', item)
      }
    },
    components: {
      TabList: () => import('./TabList.vue')
    }
  }
</script>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值