«

vue实现管理端框架结构(路由页面 ,左边导航,面包屑导航,layout布局)

yang 发布于 阅读:549 Vue2阶段


路由:

import Vue from "vue";
import VueRouter from "vue-router";
import { Message } from "element-ui";
import local from "@/utils/local.js";

Vue.use(VueRouter);

// 路由配置
const routes = [
  //访问时自动跳登陆页
  { path: "/", redirect: "/login" },

  //登陆页
  {
    path: "/login",
    component: () => import("@/views/login/LoginView.vue"),
    mete: { role: ["super"] },
  },

  // 首页
  {
    path: "/index",
    component: () => import("../views/index/LayOut.vue"),
    meta: { role: ["super", "normal"], title: "后台首页" },
    // isMenu: true, //声明要做导航的路由
    icon: "el-icon-s-home",
    children: [
      {
        path: "",
        component: () => import("@/views/index/IndexView.vue"),
        meta: { role: ["super", "normal"] },
      },
    ],
  },

  //商品管理
  {
    path: "/goods",
    component: () => import("@/views/index/LayOut.vue"),
    meta: { role: ["super", "normal"], title: "商品管理" },
    // isMenu: true, //声明要做导航的路由
    icon: "el-icon-s-goods",
    redirect: "/goods/list",
    children: [
      {
        path: "/goods/list",
        component: () => import("@/views/goods/GoodsList.vue"),
        meta: { role: ["super", "normal"], title: "商品列表" },
        // isMenu: true,
      },
      {
        path: "/goods/add",
        component: () => import("@/views/goods/GoodsAdd.vue"),
        meta: { role: ["super", "normal"], title: "添加商品" },
        // isMenu: true,
      },
      {
        path: "/goods/category",
        component: () => import("@/views/goods/GoodsCategory.vue"),
        meta: { role: ["super", "normal"], title: "商品分类" },
        // isMenu: true,
      },
      {
        path: "/goods/edit",
        component: () => import("@/views/goods/GoodsEdit.vue"),
        meta: { role: ["super", "normal"], title: "修改商品" },
      },
    ],
  },

  //订单管理
  {
    path: "/order",
    component: () => import("../views/index/LayOut.vue"),
    meta: { role: ["super", "normal"], title: "订单管理" },
    // isMenu: true, //声明要做导航的路由
    icon: "el-icon-s-order",
    children: [
      {
        path: "",
        component: () => import("@/views/order/OrderView.vue"),
        meta: { role: ["super", "normal"] },
      },
    ],
  },

  //店铺管理
  {
    path: "/shop",
    component: () => import("../views/index/LayOut.vue"),
    meta: { role: ["super"], title: "店铺管理" },
    // isMenu: true,
    icon: "el-icon-s-shop",
    children: [
      {
        path: "",
        component: () => import("@/views/shop/ShopView.vue"),
        meta: { role: ["super"] },
      },
    ],
  },

  //账号管理
  {
    path: "/account",
    component: () => import("../views/index/LayOut.vue"),
    meta: { role: ["super"], title: "账号管理" },
    // isMenu: true, //声明要做导航的路由
    redirect: "/account/list",
    icon: "el-icon-user-solid",
    children: [
      {
        path: "/account/list",
        component: () => import("@/views/account/AccountList.vue"),
        meta: { role: ["super"], title: "账号列表" },
        // isMenu: true,
      },
      {
        path: "/account/add",
        component: () => import("@/views/account/AccountAdd.vue"),
        meta: { role: ["super"], title: "添加账号" },
        // isMenu: true,
      },
      {
        path: "/account/changepassword",
        component: () => import("@/views/account/ChangePassword.vue"),
        meta: { role: ["super"], title: "修改密码" },
        // isMenu: true,
      },
      {
        path: "/account/personal",
        component: () => import("@/views/account/PersonalView.vue"),
        meta: { role: ["super"], title: "管理员信息" },
        // isMenu: true,
      },
    ],
  },

  //销售统计
  {
    path: "/count",
    component: () => import("../views/index/LayOut.vue"),
    meta: { role: ["super"], title: "销售统计" },
    // isMenu: true,
    icon: "el-icon-pie-chart",
    redirect: "/count/goods",
    children: [
      {
        path: "/count/goods",
        component: () => import("@/views/count/CountGoods.vue"),
        meta: { role: ["super"], title: "销售统计" },
        // isMenu: true,
      },
      {
        path: "/count/order",
        component: () => import("@/views/count/CountOrder.vue"),
        meta: { role: ["super"], title: "订单统计" },
        // isMenu: true,
      },
    ],
  },
];

//防止访问重复页面时报错
// 获取原型对象push函数
const originalPush = VueRouter.prototype.push;
// 修改原型对象中的push函数
VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch((err) => err);
};

const router = new VueRouter({
  routes,
});

//路由守卫
router.beforeEach(function (to, from, next) {
  // 默认访问到登录页
  if (to.path === "/login") {
    next(); //登陆页面直接放行
  } else {
    let token = local.get("token");
    // console.log("token111111111111", token);
    if (token) {
      if (to.meta.role.includes(local.get("role"))) {
        next();
      } else {
        next("/login");
      }
    } else {
      Message.error("警察叔叔还有三秒到达战场,请稍后...");
      next({ path: "/login" });
    }
  }
});

export default router;

左边导航:

<template>
  <div class="left-nav">
    <div class="title">
      <el-avatar :size="50" :src="imgUrl"></el-avatar>
      <h1>玩家外卖</h1>
    </div>

    <!-- router是开启路由模式,index是作为path一样的进行跳转 -->
    <!-- unique-opened默认只展示一个子菜单 -->
    <!-- :default-active="$route.path" 当前路由是哪个就激活那个 -->
    <el-menu
      router
      :default-active="$route.path"
      background-color="#48ac79"
      text-color="#fff"
      active-text-color="#26da6f"
      unique-opened
    >
      <div v-for="v in rolemenus" :key="v.indedivx">
        <!-- 可以展开 -->
        <el-submenu v-if="v.children" :index="v.index">
          <!-- 一级标题 -->
          <template slot="title">
            <i :class="v.icon"></i>
            <span>{{ v.tit }}</span>
          </template>
          <!-- 二级标题 -->
          <el-menu-item
            v-for="child in v.children"
            :key="child.index"
            :index="child.index"
            >{{ child.tit }}</el-menu-item
          >
        </el-submenu>

        <!-- 不可以展开 -->
        <el-menu-item v-else :index="v.index">
          <i :class="v.icon"></i>
          <span slot="title">{{ v.tit }}</span>
        </el-menu-item>
      </div>
    </el-menu>
  </div>
</template>
<script>
import { userInfo } from "@/api/user.js";
import local from "@/utils/local.js";

export default {
  data() {
    return {
      list: [
        // 首页
        {
          index: "/index",
          icon: "el-icon-s-home",
          tit: "后台首页",
          role: ["super", "normal"],
        },
        // 订单管理
        {
          index: "/order",
          icon: "el-icon-s-order",
          tit: "订单管理",
          role: ["super", "normal"],
        },
        // 商品管理
        {
          index: "/goods",
          icon: "el-icon-s-goods",
          tit: "商品管理",
          role: ["super", "normal"],
          children: [
            { index: "/goods/add", tit: "添加商品" },
            { index: "/goods/list", tit: "商品列表" },
            { index: "/goods/category", tit: "商品分类" },
          ],
        },
        // 店铺管理
        {
          index: "/shop",
          icon: "el-icon-s-shop",
          tit: "店铺管理",
          role: ["super"],
        },
        // 账号管理
        {
          index: "/account",
          icon: "el-icon-user-solid",
          tit: "账号管理",
          role: ["super"],
          children: [
            { index: "/account/add", tit: "添加账号" },
            { index: "/account/list", tit: "账号列表" },
            { index: "/account/changepassword", tit: "修改密码" },
            { index: "/account/personal", tit: "管理员信息" },
          ],
        },
        // 销售统计
        {
          index: "/count",
          icon: "el-icon-pie-chart",
          tit: "销售统计",
          role: ["super"],
          children: [
            { index: "/count/goods", tit: "商品统计" },
            { index: "/count/order", tit: "订单统计" },
          ],
        },
      ],
      //默认头像,远程地址直接使用,本地地址需要(import)引入后再使用
      imgUrl:
        "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
    };
  },

  async created() {
    //获取管理员信息
    let res = await userInfo();
    this.imgUrl = res.data.imgUrl;

    //绑定事件,接收头像参数,实现头像联动
    this.$bus.$on("upImg", (url) => {
      this.imgUrl = url; //注意this会被改指向,所以要用箭头函数
    });
  },

  computed: {
    // 权限控制
    rolemenus() {
      // 从list数组中过滤,按照角色返回相应的菜单栏
      let newarr = this.list.filter((v) => {
        return v.role.includes(local.get("role"));
      });
      return newarr;
    },
  },
};
</script>
<style lang="scss" scoped>
.title {
  display: flex;
  align-items: center;
  justify-content: space-around;
  align-content: center;
  padding: 15px 0;

  img {
    width: 50px;
    border-radius: 50%;
  }

  h1 {
    text-align: center;
    font-size: 18px;
    // color: #26da6f;
    color: #fff;
    cursor: pointer;
  }
}

:deep(.el-menu) {
  border: 0;
  background-color: #48ac79;
}

.left-nav {
  background-color: #48ac79;
  height: 100%;
}

:deep(.el-submenu__title i) {
  color: #04f759;
}

.el-menu-item i {
  color: #04f759;
}

:deep(.el-breadcrumb__separator) {
  color: #48ac79;
  z-index: 9;
}
</style>

面包屑导航:

<template>
  <div class="header">
    <!-- 面包屑导航 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item to="/login" v-if="$route.path !== '/index'"
        >后台首页</el-breadcrumb-item
      >
      <el-breadcrumb-item v-for="(v, i) in menuArr" :to="v.path" :key="i">{{
        v.name
      }}</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 管理员信息 -->
    <el-dropdown @command="jump">
      <span class="el-dropdown-link">
        欢迎{{ account }}登录
        <el-avatar :size="50" :src="imgUrl"></el-avatar>
      </span>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item command="/account/personal"
          >个人信息</el-dropdown-item
        >
        <el-dropdown-item command="/logout">退出登陆</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>
<script>
import local from "@/utils/local.js";
import { userInfo } from "@/api/user.js";

export default {
  data() {
    return {
      //默认头像,远程地址直接使用,本地地址需要(import)引入后再使用
      imgUrl:
        "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",

      //面包屑导航数据
      menuArr: [],

      //管理员名称
      account: "",
    };
  },

  methods: {
    //点击下拉菜单时执行事件处理函数
    jump(path) {
      if (path === "/logout") {
        local.clear();
        this.$router.push("/login");
      } else {
        this.$router.push(path);
      }
    },

    // 获取面包屑导航联动 matched是匹配所有的符合路由
    render() {
      let arr = this.$route.matched.filter((v) => {
        return v.meta.title;
      });

      this.menuArr = arr.map((v) => {
        return { name: v.meta.title, path: v.path };
      });
    },
  },

  // 刷新过后再次渲染
  async created() {
    this.render();

    //获取管理员信息
    let res = await userInfo();
    // console.log(res);
    local.set("userinfo", res.data); //将管理员信息存储到本地
    this.account = res.data.account;
    this.imgUrl = res.data.imgUrl;

    //绑定事件,接收头像参数,实现头像联动
    this.$bus.$on("upImg", (url) => {
      this.imgUrl = url; //注意this会被改指向,所以要用箭头函数
    });
  },

  // 监听数据改变
  watch: {
    "$route.path"() {
      this.render();
    },
  },
};
</script>
<style lang="scss" scoped>
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 60px;
}
.el-dropdown-link {
  color: #fff;
}

.el-avatar {
  vertical-align: middle;
}
</style>

layout布局:

<template>
  <div class="layout">
    <el-container>
      <!-- 左边导航 -->
      <el-aside width="200px">
        <left-nav></left-nav>
      </el-aside>

      <el-container>
        <!-- 头部 -->
        <el-header>
          <top-header></top-header>
        </el-header>

        <!-- 主体-->
        <el-main>
          <router-view></router-view>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>
<script>
export default {
  components: {
    LeftNav: () => import("@/components/LeftNav.vue"),
    TopHeader: () => import("@/components/TopHeader.vue"),
  },
};
</script>
<style lang="scss" scoped>
.layout {
  height: 100vh;
}

.el-header {
  width: 100%;
  padding: 0 15px;
  box-sizing: border-box;
  flex-shrink: 0;
  background: #48ac79;
}

:deep(.el-breadcrumb__item span) {
  color: #fff;
}

.layout > .el-container {
  height: 100%;
}

.el-aside {
  background-color: #d3dce6;
}

.el-main {
  background-color: #e9eef3;
}
</style>

注意:web端项目框架构建!!!!

版权所有:微4e
文章标题:vue实现管理端框架结构(路由页面 ,左边导航,面包屑导航,layout布局)
除非注明,文章均为 微4e 原创,请勿用于任何商业用途,禁止转载

推荐阅读:


扫描二维码,在手机上阅读
请先 登录 再评论