1. 程式人生 > 實用技巧 >Vue + Element UI 實現許可權管理系統 前端篇(七):功能元件封裝

Vue + Element UI 實現許可權管理系統 前端篇(七):功能元件封裝

因為我暫時不需要第五章和第六章教程的內容所以直接進入第七章。感興趣的可以訪問原作者網站

Vue + Element UI 實現許可權管理系統 前端篇(六):更換面板主題 Vue + Element UI 實現許可權管理系統 前端篇(五):國際化實現
注:本次封裝的css樣式應該有點問題,但考慮時間問題沒有認真修改,後續有時間重構時候補上。

元件封裝

模組化,提升後期的可維護性

元件結構

Home.vue

<template>
    <div class="container">
        <!-- 頭部區域 -->
        <header-bar></header-bar>
        <!-- 導航選單欄 -->
        <menu-bar></menu-bar>
        <!-- 主要內容區域 -->
        <main-c></main-c>
    </div>
</template>

<script>
    import HeaderBar from 
'./HeadBar/HeadBar'; import MenuBar from './MenuBar/MenuBar'; import MainC from './Main/Main' export default { components: { HeaderBar, MenuBar, MainC } } </script> <style lang="scss" scoped> .container { position: absolute; top:
0; bottom: 0; left: 0; right: 0; background: #4b5f6e; } </style>

HeadBar.vue

<template> 
    <div class="header-container">
        <!-- 導航選單隱藏顯示切換 -->
        <!-- icon @click.prevent: 阻止預設行為 -->
        <span class="collapse-switcher" @click.prevent="collapse">
        <i class="el-icon-menu"></i>
        </span>
        <!-- 導航選單 -->
        <span class="nav-bar">
            <el-menu
                :
default-active="activeIndex" class="el-menu-demo" background-color="#4b5f6e;" text-color="#fff" active-text-color="#ffd04b" mode="horizontal" @select="handleSelectHearNavBar" > <!-- index 唯一標誌 預設值 null --> <el-menu-item index="1" @click="$router.push('/')">首頁</el-menu-item> <el-menu-item index="2">訊息中心</el-menu-item> <el-menu-item index="3">訂單管理</el-menu-item> </el-menu> </span> <span class="tool-bar"> <!-- 使用者資訊 --> <el-dropdown class="user-info-dropdown" trigger="hover"> <span class="el-dropdown-link userinfo-inner"> <img :src="this.userAvatar" /> {{ username }} </span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>我的訊息</el-dropdown-item> <el-dropdown-item>設定</el-dropdown-item> <!-- 自定義元件 @click + .native 後才能觸發 --> <el-dropdown-item divided @click.native="logout">退出登入</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </span> </div> </template> <script> import mock from "@/mock/index.js"; export default { data() { return { isCollapse: false, username: "Louis", userAvatar: "", activeIndex: '1' }; }, methods: { selectNavBar(key, keyPath) { console.log(key, keyPath) }, //摺疊導航欄 collapse: function() { this.isCollapse = !this.isCollapse; }, //退出登入 logout: function() { var _this = this; this.$confirm("確認退出嗎?", "提示", { type: "warning" }) .then(() => { sessionStorage.removeItem("user"); this.$router.push ("/login"); }) .catch(() => {}); } }, mounted() { this.sysName = "I like Kitty"; var user = sessionStorage.getItem("user"); if (user) { this.userName = user; this.userAvatar = require("@/assets/user/user.png"); } } }; </script> <style scoped lang="scss"> .header-container { position: absolute; left: 200px; right: 0; height: 60px; line-height: 60px; .collapse-switcher { width: 40px; float: left; cursor: pointer; background: #504e6180; color: #fff; border: 1 solid rgba(111, 123, 131, 0.8); } .nav-bar { margin-left: auto; float: left; .el-menu { background: #504e6180; } } .tool-bar { float: right; .user-info-dropdown { font-size: 20px; padding-right: 20px; color: #fff; cursor: pointer; img { width: 40px; height: 40px; border-radius: 10px; margin: 10px 0px 10px 10px; float: right; } } } } </style>

MenuBar.vue

<template>
    <div class="menu-bar-container">
        <!-- logo -->
        <div class="logo" :class="isCollapse?'menu-bar-collapse-width':'menu-bar-width'">
            <img :src="this.logo" /> <div>{{isCollapse?'':sysName}}</div>
        </div>
        <!-- 導航選單 -->
        <el-menu 
                default-active="1-1"
                class="el-menu-vertical-demo"
                :collapse="isCollapse"
                @open="handleopen"
                @close="handleclose"
                @select="handleselect"
        >
            <!-- 這裡的兩個 slot 不懂 -->
            <el-submenu index="1">
                <template slot="title">
                    <i class="el-icon-location"></i>
                    <span slot="title">系統管理</span>
                </template>
                <el-menu-item index="1-1" @click="$router.push('user')">使用者管理</el-menu-item>
                <el-menu-item index="1-2" @click="$router.push('dept')">dept</el-menu-item>
                <el-menu-item index="1-3" @click="$router.push('role')">role</el-menu-item>
                <el-menu-item index="1-4" @click="$router.push('menu')">選單管理</el-menu-item>
                <el-menu-item index="1-5" @click="$router.push('log')">log</el-menu-item>
            </el-submenu>
            <el-submenu index="2">
                <template slot="title">
                    <i class="el-icon-location"></i>
                    <span slot="title">系統監控</span>
                </template>
                <el-menu-item index="2-1" @click="$router.push('user')">服務監控</el-menu-item>
                <el-menu-item index="2-2" @click="$router.push('menu')">任務監控</el-menu-item>
            </el-submenu>
            <el-menu-item index="3" disabled>
                <i class="el-icon-document"></i>
                <span slot="title">導航三</span>
            </el-menu-item>
            <el-menu-item index="4">
                <i class="el-icon-setting"></i>
                <span slot="title">導航四</span>
            </el-menu-item>
        </el-menu>
    </div>
</template>

<script>
    import mock from '@/mock/index.js';
    export default {
        name: 'Home',
        data() {
            return {
                isCollapse: false,
                sysName: "",
                logo: "",
            }
        },
        methods: {
            handleopen() {
                console.log('handleopen');
            },
            handleclose() {
                console.log('handleclose'); 
            },
            handleselect(a, b) {
                console.log('handleselect');
            },
        },
        // 頁面屬性初始化
        mounted() {
            this.sysName = "I like Kitty";
            this.logo = require("@/assets/user/logo.png");
        }
    }
</script>

<style scoped lang="scss">
.menu-bar-container {
  .el-menu {
    position:absolute;
    top: 60px;
    bottom: 0px;
    text-align: left;
  }
  .logo {
    position:absolute;
    top: 0px;
    height: 60px;   
    line-height: 60px;
    background: #4b5f6e;
    img {
        width: 40px;
        height: 40px;
        border-radius: 0px;
        margin: 10px 10px 10px 10px;
        float: left;
    }
    div {
      font-size: 22px;
      color: white;
      text-align: left;
    }
  }
  .menu-bar-width {
    width: 200px;
  }
  .menu-bar-collapse-width {
    width: 65px;
  }
}
</style>

Main.vue

<template>
  <div class="main-container">
    <el-breadcrumb separator="/" class="breadcrumb">
      <el-breadcrumb-item v-for="item in $route.matched" :key="item.path">
        <a href="www.baidu.com">{{ item.name }}</a>
      </el-breadcrumb-item>
    </el-breadcrumb>
    <transition name="fade" mode="out-in">
      <router-view></router-view>
    </transition>
  </div>
</template>

<script>
export default {
  data() {
    return {
    };
  },
  methods: {

  },
  mounted() {

  }
};
</script>

<style scoped lang="scss">
.main-container {
  position: absolute;
  top: 60px;
  bottom: 0px;
  left: 200px;
  right: 0px;
  background: #fff;
  .breadcrumb {
    padding: 10px;  
    border-color: rgba(38, 86, 114, 0.2);
    border-bottom-width: 1px;
    border-bottom-style: solid;
    background: rgba(138, 158, 170, 0.2);
  }
}
</style>

然後修改路由

import Vue from "vue";
import VueRouter from "vue-router";
 

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "Home",
    component: () => import ("@/views/home"),
    children: [
        { path: '', name: '系統介紹', component: () => import ("@/views/Intro") },
        { path: '/user', name: '使用者管理', component: () => import ("@/views/SysMng/User") },
        { path: '/dept', name: '系統介紹', component: () => import ("@/views/SysMng/Dept") },
        { path: '/role', name: '系統介紹', component: () => import ("@/views/SysMng/Role") },
        { path: '/menu', name: '選單管理', component: () => import ("@/views/SysMng/Menu") },
        { path: '/log', name: '系統介紹', component: () => import ("@/views/SysMng/Log") },
    ]
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import ("@/views/common/Login")
  },
  {
    path: '/404',
    name: 'notFound',
    component: () => import ("@/views/common/404")
  }
];

const router = new VueRouter({
  routes
});

// 導航守衛
router.beforeEach((to, from, next) => {
    // 登入介面成功之後,會把使用者資訊儲存在會話
    // 存在時間為會話生命週期,頁面關閉既失效
    let user = sessionStorage.getItem('user');
    if(to.path == '/login') {
        // 訪問登入介面,如果使用者會話資訊存在,代表已登入過,轉跳到主頁
        if(user) {
            next({ path: '/' })
        }else {
            next()
        }
    }else {
        // 訪問非登入介面,且使用者資訊不存在,代表未登入,則轉跳到登入介面
        if(!user) {
            next({ path: '/login' })
        }else {
            next()
        }
    }
})
export default router;

顯示效果