background

New company before the project hasn’t done Taiwan before and after separation, use didn’t this time of the project, make a background management system, is familiar with familiar with the business, the project is based on the vue + elementUI, although the vue exposed to a period of time, but not do after Taiwan management the work, in the writing in the process of doing a learn some knowledge, for future reference .

The effect

implementation


1. Page area division

The desired effect

Click on the left option to display a different page in rightContent.vue on the rightCopy the code

Home.vue

<template>
    <div class="home">
        <Header></Header>
        <div class="main">
            <LeftMenu></LeftMenu>
            <RightContent></RightContent>
        </div>
    </div>
</template>
import LeftMenu from '@/components/admin/common/LeftMenu.vue';
import RightContent from '@/components/admin/common/RightContent.vue';
import Header from '@/components/admin/common/Header.vue';

export default {
    name: 'home',
    components: {
        LeftMenu,
        RightContent,
        Header,
    },
    data() {
        return{}; },created() {// Get the default route object and save the global variable this.inittabList (); }, computed: {// Current modulemenuModule() {
            return this.$store.state.menuModule; }, // label stacktabList() {
            return this.$store.state.tabList; },}, methods: {/** *@description: saves the default route object of the home page of the current module *@param{} *@return: * /initTabList() {
            // console.log(this.$route.path); Const firstRoute = this.$router.options.routes.filter(item => item.name === this.menuModule)[0]; // Loop the children const {redirect} = firstRoute;if (firstRoute && redirect) {
                const saveRoute = firstRoute.children.filter(item => item.path === redirect)[0];
                if (saveRoute) {
                    this.tabList.push(saveRoute);
                    this.$store.commit('tabList', this.tabList); }}},},}; </script>Copy the code

2. Route implementation

I need to mention routing separately, because I have never encountered this kind of routing before. I need the effect that the content area on the right will change after clicking on the sidebar, so I thought that the page change can be solved by nesting routine. Use router-View to match routes inside RightContent.vue.

Rightcontent. vue router-view corresponding routing idea

/ index - > / home page menu - > function/menu/page1 - > function 1 / menu/page2 2 - > functionCopy the code

RightContent.vue

<template>
    <div class="right-content">
        <div class="content-item">
            <el-tabs v-model="activeTabsName" type="card" closable @tab-remove="removeTab"  @tab-click="tabClick">
                <el-tab-pane
                    v-for="(item) in tabList"
                    :key="item.path"
                    :label="item.name"
                    :name="item.name"> // Match the left route here <router-view></router-view> </el-tab-pane> </el-tabs> </div> </div> </template> <script>export default {
    name: 'RightContent', Components: {}, computed: {// label routing stacktabList() {
            return this.$store.state.tabList; }, // Active TAB activeTabsName: {get() {
                return this.$store.state.activeTabsName;
            },
            set(val) {
                this.$store.commit('activeTabsName', val); },}, // The subscript of the current labelactiveIndex() {
            let temIndex = null;
            this.tabList.forEach((item, index) => {
                if(item.name === this.activeTabsName) { temIndex = index; }});returntemIndex; }},data() {
        return{}; }, methods: {/** *@description: remove the tag *@param{String} to delete the tag *@return: null
        */
        removeTab(targetName) {
            const tabs = this.tabList;
            let activeName = this.activeTabsName;
            if (activeName === targetName) {
                tabs.forEach((tab, index) => {
                    if (tab.name === targetName) {
                        const nextTab = tabs[index + 1] || tabs[index - 1];
                        if(nextTab) { activeName = nextTab.name; }}}); this.$store.commit('activeTabsName', activeName);
                this.$store.commit('tabList', tabs.filter(tab => tab.name ! == targetName)); this.tabClick(); }else {
                this.$store.commit('tabList', tabs.filter(tab => tab.name ! == targetName)); }}, /** *@description: tag click method *@param{} *@return: * /tabClickConst {path} = this.tabList[this.activeIndex]; const {path} = this.tabList[this.activeIndex];if (this.$route.path ! == path) this.$router.push(path); ,}}}; </script>Copy the code

router.js


import Vue from 'vue';
import Router from 'vue-router';
import Index from '@/components/admin/home/Index.vue';
import TableLevel from '@/components/admin/home/TableLevel.vue';
import Home from './views/Home.vue';
import Alarm from './views/Alarm.vue';
import Patch from './views/Patch.vue';

Vue.use(Router);
const router = new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    routes: [
        {
            path: '/',
            name: 'home',
            component: Home,
            showMenu: true,
            redirect: '/index',
            meta: {
                icon: 'el-icon-location',
            },
            children: [
                {
                    path: '/index',
                    name: 'home',
                    component: Index,
                    showMenu: true,
                    meta: {
                        icon: 'el-icon-s-grid',
                    },
                },
                {
                    path: '/funmenu',
                    name: 'Function menu',
                    component: Patch,
                    showMenu: true,
                    meta: {
                        icon: 'el-icon-remove',
                    },
                    children: [
                        {
                            path: '/funmenu/table',
                            name: 'Table Component',
                            showMenu: true,
                            meta: {
                                icon: 'el-icon-s-marketing',
                            },
                            component: Patch,
                            children: [
                                {
                                    path: '/funmenu/table/level',
                                    name: 'Multilevel header',
                                    component: TableLevel,
                                    showMenu: true,
                                    meta: {
                                        icon: 'el-icon-s-data',
                                    },
                                },
                            ],
                        },
                        {
                            path: '/funmenu/pop',
                            name: 'Popover component',
                            showMenu: true,
                            component: Alarm,
                            meta: {
                                icon: 'el-icon-bell',},},],},},],});export default router;

Copy the code

3. Navigation bar implementation

The left navigation bar uses Element’s NavMenu component template, copying the code directly, because when a menu bar is hierarchically nested, there should be a loop component inside, so it’s split into two components, Leftmenu.vue and menunav.vue

1.LeftMenu.vue

 <template>
    <div class="left-menu" :class="{fold: isCollapse===true}">
        <div class="menu-content">
            <el-menu  :default-active="$route.path" class="el-menu-vertical-demo"
                      @open="handleOpen"
                      @close="handleClose"
                      :collapse="isCollapse"
                      background-color="#545c64"
                      @select="select"
                      text-color="#fff"
                      active-text-color="#ffd04b"
                      ref="leftNavigation">
                <div class="menu-toggle" @click.prevent="control">
                    <i class="el-icon-s-fold" v-show=! "" isCollapse" title="Fold"></i>
                    <i class="el-icon-s-unfold" v-show="isCollapse" title="A"></i>
                </div>
                <template v-for="(item,index)  in $router.options.routes">
                    <template v-if="item.name === menuModule">
                        <MenuNav :key="index" :menuData="item.children"></MenuNav>
                    </template>
                </template>
            </el-menu>
        </div>
    </div>
</template>

<script>
import MenuNav from '@/components/admin/common/MenuNav.vue';
import debounce from '@/common/debounce';

export default {
    name: 'leftMenu'.data() {
        return{ de: null, }; }, computed: {// Whether the side navigation bar is openisCollapse() {
            return this.$store.state.isCollapse; }, // label routing stacktabList() {
            return this.$store.state.tabList; }, // The currently active TAB TABactiveTabsName() {
            return this.$store.state.activeTabsName; }, // The current modulemenuModule() {
            return this.$store.state.menuModule;
        },
    },
    components: {
        MenuNav,
    },
    mounted() {// FIXME temporarily comment // this.initleftmenu (); // initialize the display page this.select(this.$route.path); }, methods: {// Determine the parent route to openinitLeftMenu() {// Get all the routing objects, loop through the sub-menu, hierarchical menu tree display // get the current routelet elSubmenu = null;
            let needOpenSubmenu = false;
            const curRoute = this.$route.path;
            const allRoutes = this.$router.options.routes;
            for (leti = 0; i < allRoutes.length; i += 1) { const { children } = allRoutes[i]; // If there are child routesif(children) {// Loop child routes exit the loop if the child routes are equal to the current routefor (let j = 0; i < children.length; j += 1) {
                        // console.log('Come in');
                        if (children[j].path === curRoute) break; // If there are submenus under this menuif (children[j].children) {
                            const grandChild = children[j].children;
                            for (let z = 0; z < grandChild[z].length; z += 1) {
                                if (grandChild[z].path === curRoute) {
                                    elSubmenu = j;
                                    needOpenSubmenu = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            if (this.$refs.leftNavigation && needOpenSubmenu) {
                this.$refs.leftNavigation.open(elSubmenu); /** *@description: FIXME select route jump *@param{} *@return: */ select(index) {// select(index);if (this.$route.path ! == index) this.$router.push(index); // The currently selected tag is selected this.$store.commit('activeTabsName', this.$route.name); // Check whether there is no routing object in the routing stack. Otherwise, the routing object will not be pushedif(this.tabList.every(item => item.path ! == this.$route.path)) {
                this.tabList.push(this.$route);
                this.$store.commit('tabList', this.tabList); }}, /** *@description: FIXME open menu */handleOpen() {
            // console.log('Open menu'); }, /** *@description: FIXME close menu */handleClose() {
            // console.log('Menu closed'); }, /** *@description: Implement the control method when adding throttling or anti-shake *@param{} *@return: * /control() {
            debounce('leftmenu', () => {
                this.$store.commit('isCollapse', !this.isCollapse);
            }, 300, true); ,}}}; </script>Copy the code

2. Menunav.vue (Inner loop Component)

<template>
    <fragment>
        <template v-for="(itemss,indexss) in menuData"> <! -- Level menu --> <el-submenu :index="indexss+''"  :key="indexss"  v-if="itemss.showMenu && itemss.children"> <! -- Level menu title --> <template slot="title">
                    <i :class="itemss.meta.icon"></i>
                    <span slot="title">{{itemss.name}}</span>
                </template>
                <template v-for="(term,indext) in itemss.children"> <! -- <el-menu-item :key="term.path"
                        :index="term.path+''"
                        v-if="term.showMenu && ! term.children"
                        :class="$route.path===term.path? 'is-active':''">
                        <i :class="term.meta.icon"></i>
                        <span slot="title">{{term.name}}</span> </el-menu-item> <! The recursion loop itself --> <MenuNav v-else :key="indext" :menuData="[...term]"></MenuNav>
                </template>
            </el-submenu>
            <el-menu-item
                :key="indexss"
                :index="itemss.path+''"
                v-if="itemss.showMenu && ! itemss.children"
                :class="$route.path===itemss.path? 'is-active':''">
                <i :class="itemss.meta.icon"></i>
                <span slot="title">{{itemss.name}}</span>
            </el-menu-item>
        </template>
    </fragment>
</template>

<script>
export default {
    name: 'MenuNav',
    props: ['menuData'],
    components: {},
    data() {
        return{}; }, computed: {}, watch: { },created() {},
    mounted() {
        // console.log(this.menuData);
    },
    destroyed() {},
    methods: {},
};
</script>
Copy the code

Project git address (in constant update ~)

Chef Wang from the Flower room

Ps: Directly copy the above code should not run, it is best to pull the code from Git to run, to avoid some parts of the missing arms and legs