递归实现菜单导航
**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>
```
- vue
- 为什么要学vue
- 数据双向绑定
- vue指令
- v-bind创建HTML节点属性
- v-on绑定事件
- v-cloak
- v-text
- v-for和key属性
- v-if和v-show
- 案例1
- 自定义指令
- vue样式
- vue生命周期
- vue过滤器
- 自定义键盘修饰符
- 跨域请求
- vue组件
- 组件基础
- 引入vue文件组件
- 引入render函数作为组件
- 兄弟间组件通信
- 组件函数数据传递练习
- 路由
- 数据监听
- webpack
- vue校验
- vue笔记
- form表单中input前部分默认输入,切不可修改
- mixins
- 部署到nginx
- scope
- render
- 下载文件
- vue动态组件
- axios
- Promise
- vue进阶
- node-vue-webpack搭建
- vue事件
- 插槽
- vuex
- vuex基础
- vuex命名空间
- HTML递归?
- this.$nextTick异步更新dom
- elementui
- table
- 修改element ui样式
- form
- 优质博客
- vuex state数据与form元素绑定
- es6
- Promise