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 {
             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 {
                     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 {
         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 {
     200px;
  }
  .menu-bar-collapse-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- 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;

显示效果

原文地址:https://www.cnblogs.com/CZheng7/p/13418961.html