Vue.js递归组件实现动态树形菜单
-
现在很多项目的菜单都是动态生成的,之前自己做项目也是遇到这种需求,翻看了官网案例,和网上大神的案例.只有两个感觉,官网的案例太简洁,没有什么注释,看起来不太好理解,大神们的作品又比较复杂,对于初学者来说理解起来还是有难度,自己捣鼓了几天,勉强理解了递归组件菜单的实现,这里结合官网的案例,把代码和注释附上.
-
如果你的项目是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数据格式一样就可以直接用了