🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
递归实现菜单导航 **1. 递归组件** ``` <template> <el-submenu :index="index" v-if="hasChildren"> <template slot="title"> <!-- 一级菜单图标 --> <i :class="iconCls" v-if="hasIcon"></i> <!-- 一级菜单文字 --> <span slot="title" @click.prevent="menuClick">{{ title }}</span> </template> <naf-menu-item v-for="(item, idx) in children" :key="idx" :index="index + '-' + idx" :title="item.title" :children="item.children" :options="item.options" :prefix="prefix" @naf-menu-item="$emit('naf-menu-item', $event)" > </naf-menu-item> </el-submenu> <el-menu-item :index="index" @click="menuClick" v-else ><i :class="iconCls"></i> <span slot="title" v-if="title.length < 10 && !hasTooltip">{{ title }}</span> <el-tooltip slot="title" v-else :content="hasTooltip ? options.tooltip : title" placement="top" effect="light"> <span>{{ title.length > 9 ? title.substr(0, 9) + '...' : title }}</span> </el-tooltip> </el-menu-item> </template> <script> export default { name: 'naf-menu-item', props: { title: String, index: String, options: Object, children: Array, prefix: { type: String, default: '' }, }, methods: { menuClick() { console.debug('click menu item....'); if (this.options.url) { window.open(this.options.url, this.options.target); } else if (this.options.path) { const to = `${this.prefix}${this.options.path}`; if (to != (this.$route && this.$route.path)) { this.$router.push(to); } else { this.$emit('naf-menu-item', this.options); } } }, }, computed: { hasChildren() { return this.children && this.children.length > 0; }, hasIcon() { return this.options.icon && this.options.icon.length > 0; }, hasTooltip() { return this.options.tooltip && this.options.tooltip.length > 0; }, iconCls() { if (this.options.icon && !(this.options.icon.indexOf('el-') === 0)) { return `naf-icons naf-icon-${this.options.icon}`; } return this.options.icon; }, }, }; </script> ``` 2. 使用递归组件 ``` <template> <el-menu unique-opened background-color="#11487e" text-color="white" active-text-color="#FFD04B" ref="menu" default-active="0" class="nav-menu" v-bind="themeStyles" :collapse="isCollapse" :router="false" > <naf-menu-item v-for="(item, idx) in menuItems" :key="idx" :index="idx.toString()" :title="item.title" :options="item.options" :children="item.children" :target="item.target" :prefix="routerPrefix" @naf-menu-item="$emit('naf-menu-item', $event)" > </naf-menu-item> </el-menu> </template> <script> import NafMenuItem from './menu-item'; export default { components: { NafMenuItem, }, props: { theme: String, isCollapse: Boolean, menuItems: Array, routerPrefix: { type: String, default: '' }, }, data() { return { msg: 'Use Vue 2.0 Today!', // menus, }; }, // mounted: function() { // this.$nextTick(_ => { // // Code that will run only after the // // entire view has been rendered // this.$refs.menu.open('0'); // }); // }, computed: { // 计算属性的 getter themeStyles() { // `this` 指向 vm 实例 if (this.theme === 'dark') { // dark styles return { backgroundColor: '#545c64', textColor: '#fff', activeTextColor: '#ffd04b', }; } // default styles return { backgroundColor: undefined, textColor: undefined, activeTextColor: undefined, }; }, backgroundColor() { return this.isCollapse ? '' : 'transparent'; }, }, }; </script> <style lang="less"></style> ```