返回顶部
首页 > 资讯 > 前端开发 > JavaScript >ElementUI 复杂顶部和左侧导航栏实现示例
  • 749
分享到

ElementUI 复杂顶部和左侧导航栏实现示例

2024-04-02 19:04:59 749人浏览 八月长安
摘要

描述:如图 项目路径如下图所示: 代码实现: 首先在store.js中添加两个状态: import Vue from 'vue' import Vuex from 'vuex'

描述:如图

项目路径如下图所示:

代码实现:

首先在store.js中添加两个状态:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
    topNavState: 'home',
    leftNavState: 'home'
}
export default new Vuex.Store({
    state
})

App.vue内容:

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>
<script>
  export default {
    name: 'app'
  }
</script>

main.js代码:

import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import store from './store.js'
import 'element-ui/lib/theme-chalk/index.CSS'
import '@/assets/iconfont.css'
import '@/assets/css/style.css'
Vue.config.productionTip = false
Vue.use(ElementUI)

new Vue({
    router,
    store,
    el: '#app',
    render: h => h(App)
})

router/index.js文件声明路由:

其中:行程计划、任务、通讯录属于首页大板块(topNavState=“home”);企业信息、车辆信息、部门信息都属于enterprise这一大板块(topNavState=“enterprise”)

import Vue from 'vue'
import Router from 'vue-router'
import LeftNav from '@/components/nav/leftNav.vue'
import Home from '@/views/home.vue'
import Dashboard from '@/views/workbench/dashboard.vue'
import Mission from '@/views/workbench/mission/mission.vue'
import Plan from '@/views/workbench/plan.vue'
import Maillist from '@/views/workbench/maillist.vue'
import EnterpriseList from '@/views/enterprise/index.vue'
import EnterpriseAdd from '@/views/enterprise/add.vue'
import EnterpriseDetail from '@/views/enterprise/detail.vue'
import EnterpriseValidate from '@/views/enterprise/validate.vue'
import VehicleManage from '@/views/vehicle/index.vue'
import DeptManager from '@/views/dept/index.vue'
import NotFound from '@/components/404.vue'

// 懒加载方式,当路由被访问的时候才加载对应组件
const Login = resolve => require(['@/views/login'], resolve)

Vue.use(Router)

let router = new Router({
  routes: [
    {
      path: '/login',
      type: 'login',
      component: Login
    },
    {
      path: '*',
      component: NotFound
    },
    {
      path: '/',
      type: 'home', // 根据type区分不同模块(顶部导航)
      name: 'home', // 根据name区分不同子模块(左侧导航)
      redirect: '/dashboard',
      component: Home,
      menuShow: true,
      children: [
        {
          path: '/dashboard',
          component: LeftNav,
          name: 'dashboard', // 当前路由的name
          leaf: true, // 只有一个节点
          iconCls: 'iconfont icon-home', // 图标样式class
          menuShow: true,
          children: [
            { path: '/dashboard', component: Dashboard, name: '首页', menuShow: true }
          ]
        },
        {
          path: '/mySet',
          component: LeftNav,
          name: '我的设置',
          iconCls: 'el-icon-menu',
          menuShow: true,
          children: [
            { path: '/mySet/plan', component: Plan, name: '行程计划', menuShow: true },
            { path: '/mySet/mission', component: Mission, name: '我的任务', menuShow: true },
            { path: '/mySet/maillist', component: Maillist, name: '通讯录', menuShow: true }
          ]
        }
      ]
    },
    {
      path: '/enterpriseManager',
      type: 'enterprise',
      name: 'enterprise',
      component: Home,
      redirect: '/enterprise/list',
      menuShow: true,
      children: [
        {
          path: '/enterpriseList',
          component: LeftNav,
          name: 'enterpriseList',
          leaf: true, // 只有一个节点
          iconCls: 'iconfont icon-home', // 图标样式class
          menuShow: true,
          children: [
            { path: '/enterprise/list', component: EnterpriseList, name: '企业列表', menuShow: true },
            { path: '/enterprise/detail', component: EnterpriseDetail, name: '企业详情', menuShow: false }
          ]
        },
        {
          path: '/enterpriseAdd',
          component: LeftNav,
          name: 'enterpriseAdd',
          leaf: true, // 只有一个节点
          iconCls: 'el-icon-menu',
          menuShow: true,
          children: [
            { path: '/enterprise/add', component: EnterpriseAdd, name: '企业添加', menuShow: true }
          ]
        },
        {
          path: '/enterpriseValidate',
          component: LeftNav,
          name: 'enterpriseValidate',
          leaf: true, // 只有一个节点
          iconCls: 'el-icon-menu',
          menuShow: true,
          children: [
            { path: '/enterprise/validate', component: EnterpriseValidate, name: '企业认证', menuShow: true }
          ]
        }
      ]
    },
    {
      path: '/vehicleManager',
      type: 'enterprise',
      name: 'vehicle',
      component: Home,
      redirect: '/vehicle/list',
      menuShow: true,
      children: [
        {
          path: '/vehicleList',
          component: LeftNav,
          name: 'vehicleList',
          leaf: true, // 只有一个节点
          iconCls: 'iconfont icon-home', // 图标样式class
          menuShow: true,
          children: [
            { path: '/vehicle/list', component: VehicleManage, name: '车辆信息', menuShow: true }
          ]
        }
      ]
    },
    {
      path: '/deptManager',
      type: 'enterprise',
      name: 'dept',
      component: Home,
      redirect: '/dept/list',
      menuShow: true,
      children: [
        {
          path: '/deptList',
          component: LeftNav,
          name: 'deptList',
          leaf: true, // 只有一个节点
          iconCls: 'iconfont icon-home', // 图标样式class
          menuShow: true,
          children: [
            { path: '/dept/list', component: DeptManager, name: '部门信息', menuShow: true }
          ]
        }
      ]
    }

  ]
});

router.beforeEach((to, from, next) => {
  // console.log('to:' + to.path)
  if (to.path.startsWith('/login')) {
    window.localStorage.removeItem('access-user')
    next()
  } else if(to.path.startsWith('/reGISter')){
    window.localStorage.removeItem('access-user')
    next()
  } else {
    let user = JSON.parse(window.localStorage.getItem('access-user'))
    if (!user) {
      next({path: '/login'})
    } else {
      next()
    }
  }
});

export default router

特别说明:

这里的路由对象router ,设置的是最多三级,一级路由主要对应的是顶部导航和其他无子页面的路由,二级和三级路由分别对应的是左侧导航的一级和二级菜单(比如三级路由对应的就是左侧导航的二级菜单),二级路由设置leaf属性,值为true表明该路由下没有子菜单(如果该路由下的某页面不显示在左侧导航,不算子菜单)。

leftNav.vue文件中主要是左侧导航菜单加载代码:

<template>
  <el-col :span="24" class="main">
    <!--左侧导航-->
    <aside :class="{showSidebar:!collapsed}">
      <!--展开折叠开关-->
      <div class="menu-toggle" @click.prevent="collapse">
        <i class="iconfont icon-outdent" v-show="!collapsed" title="收起"></i>
        <i class="iconfont icon-indent" v-show="collapsed" title="展开"></i>
      </div>
      <!--导航菜单-->
      <el-menu :default-active="$route.path" router :collapse="collapsed" ref="leftNavigation">
        <template v-for="(issue,index) in $router.options.routes">
          <template v-if="issue.name === $store.state.leftNavState"><!-- 注意:这里就是leftNavState状态作用之处,当该值与router的根路由的name相等时加载相应菜单组 -->
            <template v-for="(item,index) in issue.children">
              <el-submenu v-if="!item.leaf" :index="index+''" v-show="item.menuShow">
                <template slot="title"><i :class="item.iconCls"></i><span slot="title">{{item.name}}</span></template>
                <el-menu-item v-for="term in item.children" :key="term.path" :index="term.path" v-if="term.menuShow"
                              :class="$route.path==term.path?'is-active':''">
                  <i :class="term.iconCls"></i><span slot="title">{{term.name}}</span>
                </el-menu-item>
              </el-submenu>
              <el-menu-item v-else-if="item.leaf&&item.children&&item.children.length" :index="item.children[0].path"
                            :class="$route.path==item.children[0].path?'is-active':''" v-show="item.menuShow">
                <i :class="item.iconCls"></i><span slot="title">{{item.children[0].name}}</span>
              </el-menu-item>
            </template>
          </template>
        </template>
      </el-menu>
    </aside>
    <!--右侧内容区-->
    <section class="content-container">
      <div class="grid-content bg-purple-light">
        <el-col :span="24" class="content-wrapper">
          <transition name="fade" mode="out-in">
            <router-view></router-view>
          </transition>
        </el-col>
      </div>
    </section>
  </el-col>
</template>
<script>
  export default {
    name: 'leftNav',
    data () {
      return {
        collapsed: false
      }
    },
    methods: {
      //折叠导航栏
      collapse: function () {
        this.collapsed = !this.collapsed;
      },
      // 左侧导航栏根据当前路径默认打开子菜单(如果当前路由是三级,则父级子菜单默认打开)
      defaultLeftNavOpened () {
        let cur_path = this.$route.path; //获取当前路由
        let routers = this.$router.options.routes; // 获取路由对象
        let subMenuIndex = 0, needOpenSubmenu = false;
        for (let i = 0; i < routers.length; i++) {
          let children = routers[i].children;
          if(children){
            for (let j = 0; j < children.length; j++) {
              if (children[j].path === cur_path) {
                break;
              }
              // 如果该菜单下有子菜单(个数>1且设置的leaf为false才有下拉子菜单)
              if(children[j].children && !children[j].leaf) {
                let grandChildren = children[j].children;
                for(let z=0; z<grandChildren.length; z++) {
                  if(grandChildren[z].path === cur_path) {
                    subMenuIndex = j;
                    needOpenSubmenu = true;
                    break;
                  }
                }
              }
            }
          }
        }
        if(this.$refs['leftNavigation'] && needOpenSubmenu) {
          this.$refs['leftNavigation'].open(subMenuIndex); // 打开子菜单
        }
      },
    },
    mounted() {
      this.defaultLeftNavOpened();
    }
  }
</script>

home.vue是后台主页组件代码

<template>
  <el-row class="container">
    <!--头部-->
    <el-col :span="24" class="topbar-wrap">
      <div class="topbar-loGo topbar-btn">
        <a href="/" rel="external nofollow"  rel="external nofollow" ><img src="../assets/logo.png" style="padding-left:8px;"></a>
      </div>
      <div class="topbar-logos" v-show="!collapsed">
        <a href="/" rel="external nofollow"  rel="external nofollow"  style="color: #fff;">车车综合管理</a>
      </div>
      <div class="topbar-title">
        <el-row v-show="$store.state.topNavState==='home'"><!-- 注意:这里就是topNavState作用之处,根据当前路由所在根路由的type值判断显示不同顶部导航菜单 -->
          <el-col :span="24">
            <el-menu :default-active="defaultActiveIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect" :router="true">
              <el-menu-item index="/">工作台</el-menu-item>
              <el-menu-item index="/enterpriseManager">企业管理</el-menu-item>
              <el-menu-item index="/orderManager">订单管理</el-menu-item>
              <el-menu-item index="/systemManager">系统管理</el-menu-item>
            </el-menu>
          </el-col>
        </el-row>
        <el-row v-show="$store.state.topNavState==='enterprise'">
          <el-col :span="24">
            <el-menu :default-active="defaultActiveIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect" :router="true">
              <el-menu-item index="/enterpriseManager">企业信息</el-menu-item>
              <el-menu-item index="/vehicleManager">车辆信息</el-menu-item>
              <el-menu-item index="/deptManager">组织架构</el-menu-item>
            </el-menu>
          </el-col>
        </el-row>
      </div>
      <div class="topbar-account topbar-btn">
        <el-dropdown trigger="click">
          <span class="el-dropdown-link userinfo-inner">
            <i class="iconfont icon-user"></i> {{nickname}}   <i class="el-icon-caret-bottom"></i></span>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item>
              <div @click="jumpTo('/user/profile')"><span style="color: #555;font-size: 14px;">个人信息</span></div>
            </el-dropdown-item>
            <el-dropdown-item>
              <div @click="jumpTo('/user/changepwd')"><span style="color: #555;font-size: 14px;">修改密码</span></div>
            </el-dropdown-item>
            <el-dropdown-item divided @click.native="logout">退出登录</el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
    </el-col>

    <!--中间-->
    <transition name="fade" mode="out-in">
      <router-view></router-view>
    </transition>
  </el-row>
</template>
<script>
  export default {
    name: 'home',
    data () {
      return {
        defaultActiveIndex: "/",
        loading: false,
        nickname: '',
        collapsed: false
      }
    },
    created() {// 组件创建完后获取数据,
      // 此时 data 已经被 observed 了
      this.fetchNavData();
    },
    methods: {
      handleSelect(index){
        this.defaultActiveIndex = index;
      },
      //折叠导航栏
      collapse () {
        this.collapsed = !this.collapsed;
      },
      fetchNavData () { // 初始化菜单激活项
        var cur_path = this.$route.path; //获取当前路由
        var routers = this.$router.options.routes; // 获取路由对象
        var nav_type = "", nav_name = "";
        for (var i = 0; i < routers.length; i++) {
          var children = routers[i].children;
          if(children){
            for (var j = 0; j < children.length; j++) {
              var grand_children = children[j].children;
              if(grand_children){
                for (var k = 0; k < grand_children.length; k++) {
                  if (grand_children[k].path === cur_path) {
                    nav_type = routers[i].type;
                    nav_name = routers[i].name;
                    break;
                  }
                  // 如果该菜单下还有子菜单
                  if(children[j].children) {
                    let grandChildren = children[j].children;
                    for(let z=0; z<grandChildren.length; z++) {
                      if(grandChildren[z].path === cur_path) {
                        nav_type = routers[i].type;
                        nav_name = routers[i].name;
                        break;
                      }
                    }
                  }
                }
              }
            }
          }
        }
        this.$store.state.topNavState = nav_type;  // 改变topNavState状态的值
        this.$store.state.leftNavState = nav_name;  // 改变leftNavState状态的值
        if(nav_type == "home"){
          this.defaultActiveIndex = "/";
        } else {
          this.defaultActiveIndex = "/" + nav_name + "Manager";
        }
      },
      jumpTo(url){
        this.defaultActiveIndex = url;
        this.$router.push(url); //用go刷新
      },
      logout(){
        //logout
        let that = this;
        this.$confirm('确认退出吗?', '提示', {
          confirmButtonClass: 'el-button--warning'
        }).then(() => {
          //确认
          localStorage.removeItem('access-user');
          that.$router.go('/login'); //用go刷新
        }).catch(() => {});
      }
    },
    mounted() {
      let user = localStorage.getItem('access-user');
      if (user) {
        user = JSON.parse(user);
        this.nickname = user.nickname || '';
      }
    },
    watch: {
      '$route': 'fetchNavData'  //监听router值改变时,改变导航菜单激活项
    }
  }
</script>

注意fetchNavData()这个方法,主要是根据当前跳转的路由,去找到这个路由对应的type(对应顶部导航栏的分类)和name(对应左侧导航栏的分类),然后保存type和name到$store中,这样在顶部导航可以根据$store中的type显示相应的菜单,同样在左侧导航就可以取到这个name值并显示相应的左侧菜单栏了。

之前写的左侧导航栏(leftNav.vue)的代码有个不足的地方——当前打开页面是三级路由(也就是左侧导航的二级菜单)时,刷新当前页,(在左侧导航中)当前路由所属的一级菜单没有默认打开。

解决方案已修改,在leftNav.vue中添加defaultLeftNavOpened()方法,详情可以回看leftNav.vue的代码。

对于这个项目的demo,也放到了GitHub共享,请看github地址:https://github.com/yqrong/ccproject.git

最近这段时间把项目修改了下(将顶部导航也提取出来作为命名视图),详情请看下篇:

ElementUI+命名视图实现复杂顶部和左侧导航栏

补充:

今天有位细心的网友发现了一个小问题:

左侧导航当前激活的是非第一个菜单时,切换其他顶部导航再切换回来,会有两个激活的菜单。

解决:el-menu标签缺少default-active属性设置,加上即可。

<el-menu :default-active="$route.path" router :collapse="collapsed" ref="leftNavigation">
<!-- ... -->
</el-menu>

写代码还是不够细心,自我检讨一下。

 

--结束END--

本文标题: ElementUI 复杂顶部和左侧导航栏实现示例

本文链接: https://lsjlt.com/news/144941.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • ElementUI 复杂顶部和左侧导航栏实现示例
    描述:如图 项目路径如下图所示: 代码实现: 首先在store.js中添加两个状态: import Vue from 'vue' import Vuex from 'vuex' ...
    99+
    2024-04-02
  • ElementUI复杂顶部和左侧导航栏怎么实现
    这篇文章主要介绍了ElementUI复杂顶部和左侧导航栏怎么实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇ElementUI复杂顶部和左侧导航栏怎么实现文章都会有所收获,下面我们一起来看看吧。描述:如图项目...
    99+
    2023-06-29
  • ElementUI+命名视图实现复杂顶部和左侧导航栏
    在了解了命名视图的用途后,发现用命名视图来实现复杂导航更加省力。更多知识请参考这里 这里只说明重要配置内容,其他内容配置请参考上一篇初始版本: ElementUI 复杂顶部和左侧导航...
    99+
    2024-04-02
  • ElementUI命名视图怎么实现复杂顶部和左侧导航栏
    本文小编为大家详细介绍“ElementUI命名视图怎么实现复杂顶部和左侧导航栏”,内容详细,步骤清晰,细节处理妥当,希望这篇“ElementUI命名视图怎么实现复杂顶部和左侧导航栏”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来...
    99+
    2023-06-29
  • Flutter实现底部和顶部导航栏
    Flutter底部和顶部导航栏的实现,供大家参考,具体内容如下 带文字图标的底部导航栏(使用BottomNavigationBar和BottomNavigationBarItem)来...
    99+
    2024-04-02
  • javascript 实现 左侧导航栏 右侧页面跳转
    在网页设计中,导航栏是页面重要组成部分之一,它能够有效地帮助用户找到所需要的功能页面。常见的导航栏有顶部导航和左侧导航。而在交互设计中,实现导航栏及页面跳转便需要运用一些javascript的技巧。本文将介绍如何使用javascript实现...
    99+
    2023-05-15
  • 微信小程序实现左侧导航栏
    本文实例为大家分享了微信小程序实现左侧导航栏的具体代码,供大家参考,具体内容如下 wxml <view class="content">       <view c...
    99+
    2024-04-02
  • jquery实现网页左侧导航菜单栏
    本文实例为大家分享了jquery实现网页左侧导航菜单栏的具体代码,供大家参考,具体内容如下 1.首先在<head></head>之间添加 <scrip...
    99+
    2024-04-02
  • Android Fragment实现顶部、底部导航栏
    前言 无论是顶部还是底部导航栏,都是大多数APP的标配,网络上的相关实现教程也非常之多。最近回忆起以前写的小项目,发现对这块内容有些遗忘,不妨就再整理一遍代码逻辑,记录下来,方便日后...
    99+
    2024-04-02
  • vue实现顶部左右滑动导航
    日常开发中经常用到导航这些东西,写篇文章记录下。该导航实现为点击末尾/起首位置,导航自动滑动出下一项的效果。 思路:判断当前点击项,相对与屏幕的位置,若点击的位置,满足可移动的限制,...
    99+
    2024-04-02
  • Flutter实现顶部导航栏功能
    本文实例为大家分享了Flutter实现顶部导航栏的具体代码,供大家参考,具体内容如下 import 'package:flutter/material.dart'; class A...
    99+
    2024-04-02
  • 实例讲解Vue怎么实现左侧导航栏右侧标签页功能
    Vue是一款流行的JavaScript框架,它可以用于创建强大的Web应用程序。在本文中,我们将介绍如何使用Vue实现左侧导航栏右侧标签页。首先,我们需要创建一个Vue实例,以便我们可以使用Vue的组件和指令。我们可以通过使用Vue-cli...
    99+
    2023-05-14
  • vue实现拖动左侧导航栏变大变小
    本文实例为大家分享了vue实现拖动左侧导航栏变大变小的具体代码,供大家参考,具体内容如下 <template>   <div>     <div cl...
    99+
    2024-04-02
  • jQuery插件PageSlide如何实现左右侧栏导航
    这篇文章给大家分享的是有关jQuery插件PageSlide如何实现左右侧栏导航的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。jQuery左右侧栏导航菜单插件PageSlide,...
    99+
    2024-04-02
  • 微信小程序如何实现左侧导航栏
    这篇“微信小程序如何实现左侧导航栏”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“微信小程序如何实现左侧导航栏”文章吧。wxm...
    99+
    2023-07-02
  • AmazeUI手机版页面的顶部导航条Header与侧边导航栏offCanvas怎么实现
    小编给大家分享一下AmazeUI手机版页面的顶部导航条Header与侧边导航栏offCanvas怎么实现,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!顶部导航条如...
    99+
    2023-06-09
  • CSS+HTML实现顶部导航栏的方法
    这篇文章主要介绍了CSS+HTML实现顶部导航栏的方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。html有什么特点1、简易性:超级文本标记语言版本升级采用超集方式,从而更...
    99+
    2023-06-14
  • 如何实现iview tabs顶部导航栏和模块切换栏
    这篇文章将为大家详细讲解有关如何实现iview tabs顶部导航栏和模块切换栏,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1.顶部导航栏:html: <...
    99+
    2024-04-02
  • ANDROID BottomNavigationBar底部导航栏的实现示例
    第一种介绍的就是使用开源库,因为使用开源库最简单,也更加的符合我们的审美标准,同时BottomNavigationBar还是符合当前的Material Design标准的。效果展示依赖compile'com.ashokvarma.andro...
    99+
    2023-05-30
    android bottomnavigationbar ott
  • vue实现顶部左右滑动导航的方法
    这篇文章主要讲解了“vue实现顶部左右滑动导航的方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue实现顶部左右滑动导航的方法”吧!日常开发中经常用到导航这些东西,写篇文章记录下。该导航...
    99+
    2023-06-20
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作