Vue.js递归组件实现动态树形菜单

使用Vue递归组件实现动态菜单

  • 现在很多项目的菜单都是动态生成的,之前自己做项目也是遇到这种需求,翻看了官网案例,和网上大神的案例.只有两个感觉,官网的案例太简洁,没有什么注释,看起来不太好理解,大神们的作品又比较复杂,对于初学者来说理解起来还是有难度,自己捣鼓了几天,勉强理解了递归组件菜单的实现,这里结合官网的案例,把代码和注释附上.

  • 如果你的项目是element-ui,其实它里面也有提供树形菜单,但是由于是别人封装的,所以使用起来没那么方便,大多数还是会自己配置,好了,不说那么多,还是回到递归组件上来吧

  • 先来看一下菜单的最终效果,有+号的都是可以点击展开的
  •             
  • 首先看一下项目的目录,在后台菜单数据没拿到之前,这里先演示一个模拟数据的,先在SRC文档下建一个data存放菜单数据.按照菜单层级关系写 数据里设置menuLevel是为了配置路由的,值是组件的名字

  • 接着创建两个组件,一个是菜单父组件,一个是递归的子组件,父组件代码:

  •  

    <template>
        <div>
            <ul id="demo">
                <submenu
                  class="item"
                  :model="treeData">
                </submenu>
            </ul>
        </div>
    </template>
    <script>
        // 引入菜单数据
        import data from '../../data/treeData'
        // 引入子组件
        import submenu from './submenu/submenu.vue'
        export default {
            components: {
                submenu
            },
            name: 'treeMenu',
            data () {
                return {
                    treeData: data
                }
            }
        }
    </script>
    <style scoped>
        @import './treeMenu.scss';
     </style>

     

  • 子组件代码,html部分:
  • <template>
      <div>
        <li>
          <div
            :class="{bold: isFolder}"
            @click="toggle"
            @dblclick="changeType">
            <!-- 配置路由跳转 -->
            <router-link :to="{ name: model.menuLevel }">{{ model.name }}</router-link>
            
            <span v-if="isFolder">[{{ open ? '-' : '+' }}]</span>
          </div>
          <ul v-show="open" v-if="isFolder">
            <submenu
              class="item"
              v-for="(model, index) in model.children"
              :key="index"
              :model="model">
              
            </submenu>
            <!-- <li class="add" @click="addChild">+</li> -->
          </ul>
        </li>
      </div>
    </template>

    子组件代码,js部分:

  • // 引入子组件
    import submenu from './submenu'
    export default {
        components: {
            submenu
        },
        name: 'submenu',
        props: {
            model: Object
        },
        data: function () {
            return {
            open: false
            }
        },
        computed: {
            // 是否展示+图标
            isFolder: function () {
            return this.model.children &&
                this.model.children.length
            }
        },
        methods: {
            // 单击展示子菜单
            toggle: function () {
                if (this.isFolder) {
                    this.open = !this.open
                }
            },
            // 双击给当前单一不可展开的菜单添加children,变成可展开样式
            changeType: function () {
                if (!this.isFolder) {
                    // Vue.set(this.model, 'children', [])
                    this.$set(this.model, 'children', [])
                    this.addChild()
                    this.open = true
                }
            },
            // 给子菜单添加内容
            addChild: function () {
            this.model.children.push({
                name: 'new stuff'
            })
            }
        }
    }

    路由配置,这里的name和data数据里的menuLevel一样:

  • import Vue from 'vue'
    import Router from 'vue-router'
    // import OnePage from '@/components/OnePage/OnePage'
    // 引入菜单组件
    import treeMenu from '@/components/menu/treeMenu'
    // 引入一级菜单
    import one from '@/components/one/one'
    // 引入二级菜单
    import two from '@/components/two/two'
    // 引入三级菜单
    import three from '@/components/three/three'
    
    Vue.use(Router)
    
    export default new Router({
      routes: [
        // {
        //   path: '/',
        //   name: 'OnePage',
        //   component: OnePage
        // }
        {
          path: '/',
          name: 'treeMenu',
          component: treeMenu
        },
        {
          path: '/one',
          name: 'one',
          component: one
        },
        {
          path: '/two',
          name: 'two',
          component: two
        },
        {
          path: '/three',
          name: 'three',
          component: three
        }
      ]
    })

    这样一个树形菜单就大致完成了,配置了路由的也可以跳转到相应页面,如果菜单数据是后台给你的,数据只要和你一开始设置data数据格式一样就可以直接用了

posted @ 2018-06-13 15:22  潇湘羽西  阅读(2279)  评论(0编辑  收藏  举报