布局组件_递归菜单_面包屑封装

在这里插入图片描述
router版本的错误,要么换版本,要么catch不处理
router里面添加

// 处理路由跳转的异常提示: 功能上没有问题的, 要么换3.0版本, 要么catch一下不处理不报错
const routerPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
  return routerPush.call(this, location).catch(error=> error)
}

1 不存在的页面 添加404,router-> index.js

 {
    path:'/404',
    name:'NotFound',
    component:()=> import('../views/404.vue') // 懒加载
  },
  // {
  //   path:'*',
  //   redirect:{ name:'NotFound'}
  // },

异步路由无法匹配
100行添加

  asyncRoutes.push({
    path:'*',
    redirect:{ name:'NotFound'}
  })
  • redirect
  • async
    2 添加401 非法的ajax请求
    Notification
  // 603 代表token失效, 处理跳转到权限不足页面
        console.log(response,'res',response?.data?.code)
        if (response?.data?.code === 603) { // token失效
            Notification.error({
                title: '错误',
                message: 'token失效,请重新登录'
            });
            // 替换到401页面
            router.replace('/401');
        }

62行

export const pretty = function(promise) {
    return promise.then(data=>[data,undefined])
    .catch(err=>[undefined,err]);
}

element-ui contianer容器
layout->layout.vue
URL:http://localhost:8081/#/loan-input/index

<el-container>
  <el-aside width="200px">Aside</el-aside>
  <el-container>
    <el-header>Header</el-header>
    <el-main>Main</el-main>
    <el-footer>Footer</el-footer>
  </el-container>
</el-container>

样式

<style>
  .el-header, .el-footer {
    background-color: #B3C0D1;
    color: #333;
    text-align: center;
    line-height: 60px;
  }
  
  .el-aside {
    background-color: #D3DCE6;
    color: #333;
    text-align: center;
    line-height: 200px;
  }
  
  .el-main {
    background-color: #E9EEF3;
    color: #333;
    text-align: center;
    line-height: 160px;
  }
  
  body > .el-container {
    margin-bottom: 40px;
  }
  
  .el-container:nth-child(5) .el-aside,
  .el-container:nth-child(6) .el-aside {
    line-height: 260px;
  }
</style>

删除

  body > .el-container {
    margin-bottom: 40px;
  }
  .el-container:nth-child(5) .el-aside,
  .el-container:nth-child(6) .el-aside {
    line-height: 260px;
  }

添加:

.el-container {
    height: 100%;
}
<el-main>Main</el-main> 换Main
                <router-view />
// view里面取出来的辅助函数 mapGetter
import { mapGetters,mapActions } from 'vuex'
 computed: {
        ...mapGetters({
            menus: 'user/getUserMenus'
        })
    },

添加菜单
aside里面添加

 <el-menu
      default-active="2"
      class="el-menu-vertical-demo"
      @open="handleOpen"
      @close="handleClose"
      background-color="#545c64"
      text-color="#fff"
      active-text-color="#ffd04b">
 <el-menu-item index="3" disabled>
        <i class="el-icon-document"></i>
        <span slot="title">导航三</span>
      </el-menu-item>
      <el-submenu index="1-4">
          <template slot="title">选项4</template>
          <el-menu-item index="1-4-1">选项1</el-menu-item>
        </el-submenu>

建立一个GAsindeMenu.vue,删除上述代码,复制
layout里面删除

 <el-menu-item index="3" disabled>
        <i class="el-icon-document"></i>
        <span slot="title">导航三</span>
      </el-menu-item>
      <el-submenu index="1-4">
          <template slot="title">选项4</template>
          <el-menu-item index="1-4-1">选项1</el-menu-item>
        </el-submenu>

layout里面添加

import GAsideMenu from '@/components/GAsideMenu';
 <GAsideMenu v-for="(item, i) in menus" :key="i" :item="item" /> //循环数组,数据
  components: { GAsideMenu }, // 声明组件

GAsindeMenu.vue里面

export default {
    name:'GAsideMenu', // 递归组件的核心
    props:{
        item:{
            type:Object,
            required:true
        }
    }
}
 <el-menu-item index="3" disabled>  //disabled去掉
        <i class="el-icon-document"></i>
        <span slot="title">导航三</span>
      </el-menu-item>
      <el-submenu index="1-4">
          <template slot="title">选项4</template>
          <el-menu-item index="1-4-1">选项1</el-menu-item>
        </el-submenu>

上面被替换,:index="item.path"唯一标识
v-if v-else 如果… 那么…

 <el-menu-item v-if="!item.children" :index="item.path">
                    <!-- <i class="el-icon-document"></i> 可以通过配置传递icon -->
                    <span slot="title">{{item?.meta?.title}}</span>
                </el-menu-item>
                <el-submenu v-else :index="item.path">
                    <template #title>{{item?.meta?.title}}</template>
                     <GAsideMenu v-for="(it,i) in item.children" :key="i" :item="it"/>
                </el-submenu>

删除空白菜单
menu.json修改

  {
    "path": "/",
    "redirect":"/home",
    "component":"Layout",
    "meta":{
      "title":"首页" 
    },
    "children":[
      { 
        "path":"/home",
        "component":"Home"
      }
    ]
  },

改成

 {
    "path": "/",
    "meta":{
      "title":"首页" 
    }
  },

router->index.js修改

  {
    path: '/',
    redirect:'/home',
    name: 'Home',
    meta:{
      title:'首页'
    },
    component: Layout,
    children:[
      {
        path:'/home',
        component:Home
      }
    ]
  },

添加面包屑

一个div包两个div,element-ui添加面包屑

    <div>
      <div class="left">
        <el-breadcrumb separator="/">
          <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
          <el-breadcrumb-item><a href="/">活动管理</a></el-breadcrumb-item>
          <el-breadcrumb-item>活动列表</el-breadcrumb-item>
          <el-breadcrumb-item>活动详情</el-breadcrumb-item>
        </el-breadcrumb>
      </div>
  
      <div class="right"></div>
    </div>

样式

.el-header {
  display: flex;
  align-items: center;
  justify-content: space-between; // 挨着两边
}

建立一个组件GBreadcrumb.vue
在layout.vue中

import GBreadcrumb from '@/components/GBreadcrumb';
//声明组件
    components: { GAsideMenu, GBreadcrumb },
//在left的div上加入
 <GBreadcrumb />

建立一个组件GBreadcrumb.vue

<template>
   <el-breadcrumb separator="/">
                  <el-breadcrumb-item v-for="(route, i) in breadcrumbList" :key="i">
                    <span v-if="breadcrumbList.length - 1 === i">{{ route?.meta?.title }}</span>
            <router-link v-else :to="route">{{ route?.meta?.title }}</router-link>
                
                </el-breadcrumb-item>
        </el-breadcrumb>
</template>
<script>
export default {
    name: 'GBreadcrumb',
    // v3
    computed:{
        breadcrumbList(){
            return this.$route.matched.filter(route => route?.meta?.title);
        }
    },
    // data() {
    //     return {
    //         breadcrumbList: []
    //     }
    // },
    // created(){
    //    this.breadcrumbList = this.$route.matched.filter(route => route?.meta?.title);
    // },  
    // watch: { // 监视里有
    //     $route: {
    //         deep: true,
    //         handler() {
    //             console.log(this.$route.matched, 'this.$route.matched')
    //             this.breadcrumbList = this.$route.matched.filter(route => route?.meta?.title);
    //         },
    //         immediate:true,  // v2 去掉created
    //     }
    // },

}
</script>
<style>

</style>

v-for 循环遍历,
封装组件GDropdown.vue

<template>
        <el-dropdown  @command="$emit('command',$event)">
        <span class="el-dropdown-link">
            {{title}}<i class="el-icon-arrow-down el-icon--right"></i>
        </span>
        <el-dropdown-menu slot="dropdown">
            <el-dropdown-item v-for="(item,i) in items" :command="item.key">{{ item.label }}</el-dropdown-item>
        </el-dropdown-menu>
        </el-dropdown>
</template>
<script>
export default {
    name:'GDropdown',
    // methods:{
    //     xx(e){
    //         this.$emit('command',e);
    //     }
    // },
    props: {
        title: {
            required: true,
            type: String
        },
        items: {
            type: Array,
            required: true,
        }
    }
}
</script>

<style>

</style>

GDropdown使用

import GDropdown from '@/components/GDropdown';
  components: { GAsideMenu,GBreadcrumb,GDropdown },
 <GDropdown @command="doCommand" :title="'admin'" :items="[{ key: 'logout', label: '退出' }]" />



不懂的知识点:

  1. props
  2. v-for
  3. computed

退出
modules->user.js

import {logout} from '@/apis/user';
import { Message } from 'element-ui';
  actions:{
        async doLogout({ commit,dispatch },payload){
            let [res,err] = await logout();

            // 清除各种数据
            if (err) {
                return Message.error('退出失败!!');
            }
            
            // 如果是使用dispatch异步action,也可以使用await
            commit('changeIsLogin',false);
            commit('changeUserInfo',null);
            commit('changeUserMenus',null);
            
            // 清空本地存储
            window.sessionStorage.setItem('token','');
        }
    }

layout.vue

  methods: {
        ...mapActions({
            doLogout:'user/doLogout'
        }),
        async doCommand(e) {
            if (e === 'logout') {
               let [res,err] = await this.doLogout();
               // 外部没有依赖里面的值
               // 依赖的是执行顺序
               window.location.reload();
            }
        }
    },
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值