失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > vue+elementUI项目中使用NavMenu导航菜单

vue+elementUI项目中使用NavMenu导航菜单

时间:2021-06-08 00:44:37

相关推荐

vue+elementUI项目中使用NavMenu导航菜单

vue+elementUI项目中使用NavMenu 导航菜单

在elementUI官网组件中NavMenu 导航菜单的使用只是简单地运用,在实践项目中还需要配合路由配置。一般后台管理系统不只是导航菜单的单独应用,一般会配合页面标签和面包屑功能,一步一步进行,做导航菜单功能。

网上也有好多开源的后台管理系统,github上可以直接下载。我在网上找了一个vue+elementui后台管理系统,配合功能详解,相信对你会有帮助。

1.准备工作

vue项目搭建,本人习惯用vue-cli脚手架进行快速搭建框架,大家可以直接在网上搜索,安装elementui,不太熟悉的可以点击这里,elementUI官方文档。

(1)切换到项目下,安装element-ui

# 推荐使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用。npm i element-ui -S

(2)在项目中使用element-ui:

在main.js引入,并使用

import Vue from 'vue'import App from './App'import router from './router'/*引入下面三行*/import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';Vue.use(ElementUI);Vue.config.productionTip = false/* eslint-disable no-new */new Vue({el: '#app',router,components: { App },template: '<App/>'})

这是全局应用,这样项目中的页面中就可以用引用elementui下的所有组件了。

2.功能实现

根据需要写好组件,包含公共组件及各模块所需组件,并且配置路由

(1)公共布局组件

主要代码存放结构如下图

布局组件LayOut.vue代码(其中有导航菜单,页面标签)

公共布局组件-----layout布局组件中存放内容(具体布局及样式根据需要而定)

<template><el-container style="width:100%;height:100%"><side-bar></side-bar><el-main><!-- <template> --><div><nav-bar></nav-bar><tags-view></tags-view></div><app-main></app-main><!-- </template> --></el-main></el-container></template><script>import SideBar from "@/components/common/sidebar/index"import AppMain from "@/components/common/AppMain"import NavBar from "@/components/common/navBar"import TagsView from "@/components/common/tagsview"export default {data(){return{}},components:{SideBar,AppMain,NavBar,TagsView}}</script><style lang="stylus" scoped></style>

下边是页面布局图

(2) 公共路由承载组件

公共承载组件----AppMain组件中存放内容

其中用vue内置transition标签设置动画,具体怎么设置可以在网上查到.

由于项目中引入了国际化功能,导航菜单中的国际化设置,读者引用时可以去掉。

<template><section class="app-main clearBoth"><transition name="fade-transform" mode="out-in"><keep-alive><router-view v-if="isRouterAlive && $route.meta.keepAlive" /></keep-alive></transition><transition name="fade-transform" mode="out-in"> <router-view v-if="isRouterAlive && !$route.meta.keepAlive" /></transition></section></template><script>export default {data(){return{isRouterAlive:true}}}</script><style lang="stylus" scoped>.clearBoth{clear both/* fade-transform */.fade-transform-leave-active,.fade-transform-enter-active {transition: all .5s;}.fade-transform-enter {opacity: 0;transform: translateX(-30px);}.fade-transform-leave-to {opacity: 0;transform: translateX(30px);}}</style>

菜单渲染组件sidebar(index.vue)其中使用vueX,共享侧边导航栏的收缩、展开状态,此功能如果不需要可以去掉。

<template><div class="sidebar"><logo v-if="!isCollapse"/><el-scrollbar wrap-class="scrollbar-wrapper"><el-menu:show-timeout="200" :default-active="$route.path" :collapse="isCollapse"mode="vertical" :unique-opened="false":collapse-transition="true"background-color="rgb(48, 65, 86)"text-color="#fff"class="el-menu-vertical-demo"><sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" /></el-menu></el-scrollbar></div></template><script>import { mapGetters } from 'vuex'import Logo from './Logo'import SidebarItem from './SidebarItem'export default {components: { Logo,SidebarItem },computed: {...mapGetters(['sidebar']),routes() {return this.$router.options.routesconsole.log(routes)},isCollapse() {return !this.sidebar.opened //获取侧边栏收缩状态}}}</script>

菜单渲染组件SidebarItem.vue

<template><fragment v-if="!item.hidden"><template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"><app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)"><el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}"><item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="generateTitle(onlyOneChild.meta.title)" /></el-menu-item></app-link></template><el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body><template slot="title"><i :class="item.meta.icon"></i><span slot="title">{{generateTitle(item.name)}}</span><!-- <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="generateTitle(item.meta.title)"/> --></template><sidebar-itemv-for="child in item.children":key="child.path":is-nest="true":item="child":base-path="resolvePath(child.path)"class="nest-menu"/></el-submenu></fragment></template><script>import path from 'path'import { generateTitle } from '@/utils/i18n'import { isExternal } from '@/utils/validate'import Item from './Item'import AppLink from './Link'export default {name: 'SidebarItem',components: { Item, AppLink },props: {// route objectitem: {type: Object,required: true},isNest: {type: Boolean,default: false},basePath: {type: String,default: ''}},data() {this.onlyOneChild = nullreturn {}},methods: {hasOneShowingChild(children = [], parent) {const showingChildren = children.filter(item => {if (item.hidden) {return false} else {// Temp set(will be used if only has one showing child)this.onlyOneChild = itemreturn true}})// When there is only one child router, the child router is displayed by defaultif (showingChildren.length === 1) {return true}// Show parent if there are no child router to displayif (showingChildren.length === 0) {this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }return true}return false},resolvePath(routePath) {if (isExternal(routePath)) {return routePath}if (isExternal(this.basePath)) {return this.basePath}return path.resolve(this.basePath, routePath)},generateTitle}}</script>

菜单渲染组件item.vue

<script>export default {name: 'MenuItem',functional: true,props: {icon: {type: String,default: ''},title: {type: String,default: ''}},render(h, context) {const { icon, title } = context.propsconst vnodes = []if (icon) {vnodes.push(<i class={[icon, 'sub-el-icon']} />)}if (title) {vnodes.push(<span slot='title'>{(title)}</span>)}return vnodes}}</script>

路由配置(公共组件在头部引入,各模块组件按需引入)

import Vue from 'vue'import Router from 'vue-router'import login from '@/modules/login'import register from '@/modules/register'import home from '@/modules/home'import LayOut from '@/components/common/LayOut'import adduser from '@/modules/user-manage/adduser'import deluser from '@/modules/user-manage/deluser'import authorityManage from '@/modules/authority-manage'import Tinymce from '@/modules/example/Tinymce'Vue.use(Router)export default new Router({routes: [{path: '/',name: 'login',component: login,hidden: true ,// (默认 false)当设置 true 的时候该路由不会在侧边栏出现 如401,login等页面meta: {keepAlive: false}},{path: '/register',name: 'register',hidden: false, component: register,meta: {keepAlive: false}},{path: '/home',name: 'home',component: LayOut,redirect:'/home/index',meta: {keepAlive: false,title: 'home',icon: 'el-icon-s-home'},children:[{path: '/home/index',component:home,name: 'home',meta: {title: 'home',icon: 'el-icon-s-home'},}]},{path: '/userManage',component: LayOut,name: 'userManage',redirect:'/userManage/adduser',meta: {title: 'userManage',icon: 'el-icon-user'},children: [{path: '/userManage/adduser',name: 'adduser',meta: {title: 'adduser',},component:adduser,}, {path: '/userManage/deluser',name: 'deluser',meta: {title: 'deluser',},component:deluser,},]},{path: '/authority-manage',component: LayOut,name: 'authorityManage',children: [{path: '/authority-manage/index',component: authorityManage,name: 'authorityManage',meta: {title: 'authorityManage',icon: 'el-icon-lock'},}]},{path: '/example',component: LayOut,redirect: '/example/tinymce',name: 'example',alwaysShow:true,//如果菜单中只有一个子菜单时,true为显示此菜单,为false则只显示子菜单meta: {title: 'example',icon: 'el-icon-edit-outline'},children: [{path: '/example/tinymce',component: Tinymce,name: 'tinymce',meta: { title: 'tinymce', icon: 'edit' }},]},]})

路由个配置项的详细讲解。

(3)各模块对应组件

各模块组件这里不做介绍,根据需要写入内容,保持路由中引入正确即可

截图这是我写的小例子中的组件位置,看读者需要自行设计。

按照以上的操作可能在打包的时候element-UI的图标会不显示,出现报错如图

问题原因:

(1)查看 /build/webpack.base.conf.js 文件可以发现,woff 或 ttf 这些字体会经由 url-loader 处理后在 static/fonts 目录下生成相应的文件。

(2)也就是说实际应该通过 /static/fonts/** 路径来获取字体图标,而实际却是请求 /static/css/static/fonts/**,自然报 404 错误。

解决办法:

1、webpack module配置:(build目录下webpack.base.conf.js)

module: {rules: [...(config.dev.useEslint ? [createLintingRule()] : []),{test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,loader: 'url-loader',options: {limit: 10000,name: utils.assetsPath('fonts/[name].[hash:7].[ext]')}}]},

2、webpack utils.js 修改:(build目录下utils.js)中添加 publicPath: ‘…/…/’

if (options.extract) {return ExtractTextPlugin.extract({use: loaders,fallback: 'vue-style-loader',publicPath: '../../' //添加这一句})} else {return ['vue-style-loader'].concat(loaders)}

这样就不会报错,图标也显示了.

以上只是侧边栏的配置希望对你有一些帮助,其他布局后续完善。

如果觉得《vue+elementUI项目中使用NavMenu导航菜单》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。