三、b站尚硅谷VUE项目硅谷甄选3

对layout界面的搭建

1.logo组件的封装

将右侧的图标和标题封装到一个ts文件
新建layout/logo/index.vue,存放左侧标题与图片

<template>
    <div class="logo" v-if="setting.logoHidden">
        <img :src="setting.logo" alt="" >
        <p>{{setting.title}}</p>
    </div>
</template>

<script setup lang="ts">
//引入设置标题与logo配置文件
import setting from '@/setting';
</script>

<style scoped lang="scss">
.logo {
    width: 100%;
    height: $base-menu-logo-height;
    color: white;
    display: flex;
    align-items: center;
    padding: 20px;

    img {
        width: 40px;
        height: 40px;
    }

    p {
        font-size: $base-logo-title-fontSize;
        margin-left: 10px;
    }

}
</style>

TIPS:双大括号 {{ }} 是用来进行文本插值的语法
在layout/index.vue引入左侧菜单logo子文件

<!-- 左侧菜单 -->
        <div class="layout_slider">
            <Logo></Logo>

        </div>
import Logo from './logo/index.vue'

新建src/setting.ts,对图片与标题进行封装

// 用于项目logo|标题配置
export default {
    title: '硅谷甄选运营平台',//项目标题
    logo: '/public/logo.png',//项目logo设置
    logoHidden: true//logo组件是否隐藏
}

在这里插入图片描述

2.左侧菜单静态搭建

以后的菜单要根据用户的路由进行搭建,本章这里写成静态页面
layout/index.vue

<div class="layout_container">
        <!-- 左侧菜单 -->
        <div class="layout_slider">
            <Logo></Logo>
            <!-- 展示菜单 -->
            <!-- 滚动组件 -->
            <el-scrollbar class="scrollbar">
                <!--放置菜单组件 -->
                <el-menu background-color=" $base-menu-background" text-color="white">
                    <el-menu-item index="1">首页</el-menu-item>
                    <el-menu-item index="2">数据大屏</el-menu-item>
                    <!-- 折叠菜单 -->
                    <el-sub-menu index="3">
                        <template #title>
                            <span>权限管理</span>
                        </template>
                        <el-menu-item index="3-1">用户管理</el-menu-item>
                        <el-menu-item index="3-2">角色管理</el-menu-item>
                        <el-menu-item index="3-3">菜单管理</el-menu-item>
            

                    </el-sub-menu>

                </el-menu>

            </el-scrollbar>

        </div>
.layout_slider {
        // 宽度写成全局变量可以随时改
        width: $base-menu-width;
        height: 100vh;
        background-color: $base-menu-background;
        color: white;

        .scrollbar {
            width: 100%;
            height: calc(100vh - $base-menu-logo-height);
        }

    }

在这里插入图片描述

3.递归组件生成动态菜单

上述菜单写的是静态,我们需要根据路由动态生成菜单
可以封装成组件动态生成菜单
新建src/layout/menu/index.vue
在layout/index.vue引入菜单组件

// 引入菜单组件
import Menu from './menu/index.vue'

3.1在登录界面添加二级路由

在router/routers.ts添加二级路由

 // 登录成功展示数据的路由
        path: '/',
        component: () => import('@/layout/index.vue'),
        name: 'layout',
        meta:{
            title:'layout',//菜单标题
            hidden:false,
        },
        children:[{
            path:'/home',
            component:()=>import('@/views/home/index.vue'),
            meta:{
                title:'首页',//菜单标题
                hidden:false,
            }
        },{
            path:'/ceshi',
            component:()=>import('@/views/home/index.vue'),
            meta:{
                title:'测试',//菜单标题
                hidden:false,
            }
        }
    ]

3.2 把路由的数组存储到仓库当中

便于菜单组件引入
在store/modules/user.ts

// 引入常量路由
import { constantRoute } from '@/router/routes';

挂载到仓库中:

let useUserStore = defineStore('User', {
    // 小仓库存储数据的地方
    // state函数返回对象的类型没有定义
    state: (): UserState => {
        return {
            token: GET_TOKEN(),//用户唯一标识token
            menuRoutes: constantRoute,//仓库存储生成菜单需要数组(路由)
        }
    },

仓库中没有menuRoutes字段,这个字段是数组,数组存放路由对象,需要定义state数据类型
进入store/modules/types/type.ts文件

import type { RouteRecordRaw } from "vue-router";
// 定义小仓库数据state类型
export interface UserState{
    token:string|null;
    menuRoutes:RouteRecordRaw[]
}

vue-router提供这个路由对象的类型,引入即可

3.3layout组件获取小仓库的数据

在layout/index.vue引入组件

// 获取用户相关的小仓库
import useUserStore from '@/store/modules/user';
let userStore = useUserStore();

我把你需要的路由数组传给组件menu了

 <!-- 根据路由动态生成菜单组件 -->
  <Menu :menuList = "userStore.menuRoutes"></Menu>

3.4获取父组件

在layout/menu/index.vue中获取父组件传递传递过来的全部组件

// 获取父组件传过来的所有路由数组
defineProps(['menuList'])

给每一个路由添加路由元信息meta,用来展示路由的标题

meta:{
            title:'layout',//菜单标题
            hidden:false,
        },

撰写菜单界面:
1.通过v-for四次循环遍历一级路由
2.通过递归组件遍历二级路由

<template>

    <template v-for="(item, index) in menuList" :key="item.path">
        <!-- 没有子路由 -->
        <template v-if="!item.children">
            <el-menu-item :index="item.path" v-if="!item.meta.hidden">
                <!-- 具名插槽 -->
                <template #title>
                    <span>图标 &nbsp</span>
                    <span>{{ item.meta.title }}</span>
                </template>

            </el-menu-item>

        </template>

        <!-- 有子路由但是只有一个 -->
        <template v-if="item.children && item.children.length == 1">
            <el-menu-item  :index="item.children[0].path" v-if="!item.children[0].meta.hidden">
            <template #title>
                <span>{{ item.children[0].meta.title }}</span>

            </template>

        </el-menu-item>

        </template>
        
        <!-- 有子路由不止一个 -->
        <template>
            
        </template>
        <el-sub-menu :index="item.path" v-if="item.children && item.children.length > 1">
            <template #title>
                <span>{{ item.meta.title }}</span>

            </template>
            <!-- 递归组件必须要有名字 -->
            <Menu :menuList="item.children"></Menu>

        </el-sub-menu>

    </template>
</template>

(注意:递归组件一定要有名字)

<script lang="ts">
export default {
    name: 'Menu'
}
</script>

小细节:取消右侧白色边框
el-menu在.scrollbar属性下面,添加border-right: none;

.scrollbar {
            width: 100%;
            height: calc(100vh - $base-menu-logo-height);
            .el-menu{
                border-right: none;
            }
        }

并不是所有的路由都在菜单里面展示,在路由元信息添加属性hidden,是否隐藏
会有两个判断,一个判断是否有二级路由 一个判断是否隐藏,解决方法是在标签外置一个标签template,放置判断语句

<template v-if="!item.children">
            <el-menu-item :index="item.path" v-if="!item.meta.hidden">

4.菜单图标完成

将element-plus图标变成全局组件,这样可以在项目所有地方任意使用
element官网有具体步骤
1.在component/index.ts文件注册所有图标

// 引入element-plus提供的图标组件
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
// 将element-plus图标注册为全局组件
        
        for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
            app.component(key, component)
          }

    }

2.给每个路由添加图标字段
router/routers.ts

{
        // 登录路由
        path: '/login',
        component: () => import('@/views/login/index.vue'),
        name: 'login',//命名路由
        meta:{
            title:'登录',//菜单标题
            hidden:true,//代表路由标题在菜单中是否影藏
            icon:"Promotion"//菜单文字左侧图标,支持element-plus全部图标
        }
    },

3.menu/index.vue中写入图标组件

使用全局组件 component加载图标

 <el-icon>
	  <component :is="item.meta.icon"></component>
 </el-icon>

4.menu-item点击事件进行路由跳转
折叠图标没有点击事件

<el-menu-item :index="item.path" v-if="!item.meta.hidden" @click="goRoute">
// 点击菜单的回调
const goRoute=(vc:any)=>{
    console.log(vc.index);

}

5.项目全部路由配置

在views 新建acl和product文件夹放置界面
在这里插入图片描述
在routes.ts文件里配置路由

{
        path: '/screen',
        component: () => import('@/views/screen/index.vue'),
        name: 'Screen',
        meta: {
            title: '数据大屏',//菜单标题
            hidden: false,
            icon: "DataBoard"

        }

    },
    {
        path: '/acl',
        component: () => import('@/layout/index.vue'),
        name: 'Acl',
        meta: {
            title: '权限管理',//菜单标题
            hidden: false,
            icon: "Lock"
        },

        children: [{
            path: '/acl/user',
            component: () => import('@/views/acl/user/index.vue'),
            name: 'User',
            meta: {
                title: '用户管理',//菜单标题
                hidden: false,
                icon: "User"
            }
        }, {
            path: '/acl/role',
            component: () => import('@/views/acl/role/index.vue'),
            name: 'Role',
            meta: {
                title: '权限管理',//菜单标题
                hidden: false,
                icon: "UserFilled"
            }

        }, {
            path: '/acl/permission',
            component: () => import('@/views/acl/permission/index.vue'),
            name: 'Permission',
            meta: {
                title: '菜单管理',//菜单标题
                hidden: false,
                icon: "Monitor"
            }

        }
        ]
    },
    {
        path: '/product',
        component: () => import('@/layout/index.vue'),
        name: 'Product',
        meta: {
            title: '商品管理',//菜单标题
            hidden: false,
            icon: "Goods",
        },
        children: [{
            path: '/product/trademark',
            component: () => import('@/views/product/trademark/index.vue'),
            name: 'Trademark',
            meta: {
                title: '品牌管理',//菜单标题
                hidden: false,
                icon: "ShoppingCartFull"
            }
        }, {
            path: '/product/attr',
            component: () => import('@/views/product/attr/index.vue'),
            name: 'Attr',
            meta: {
                title: '属性管理',//菜单标题

                icon: "ChromeFilled"
            }
        }, {
            path: '/product/spu',
            component: () => import('@/views/product/spu/index.vue'),
            name: 'Spu',
            meta: {
                title: 'SPU管理',//菜单标题
                icon: "Calendar"
            }
        }, {
            path: '/product/sku',
            component: () => import('@/views/product/sku/index.vue'),
            name: 'Sku',
            meta: {
                title: 'SKU管理',//菜单标题

                icon: "Orange"
            }
        }
        ]

在menu/index.vue文件写路由跳转,通过点击事件进行跳转@click=“goRoute”
使用push方法

import { useRouter } from 'vue-router';
// 获取路由器对象
let $router = useRouter();
// 点击菜单的回调
const goRoute=(vc:any)=>{
    // 路由跳转
    $router.push(vc.index);

}

在这里插入图片描述
展示内容区域原来是router-view,现在将他封装成组件main
1.引入

// 引入菜单组件
import Menu from './menu/index.vue'
<div class="layout_main">
            <Main></Main>
        </div>

可以在main组件加入一些过渡动效
在vue官网查看vue-router–进阶—过渡动效

<template>
    <div>
        <!-- 路由组件出口的位置 -->
        <router-view v-slot="{ Component }">
            <transition name="fade">
                <!-- 渲染layout一级组件的子路由 -->
                <component :is="Component" />
            </transition>
        </router-view>
    </div>
</template>

<script setup lang="ts">

</script>

<style scoped>
.fade-enter-from {
    opacity: 0;
    transform: scale(0);

}

.fade-enter-active {
    transition: all .3s;
}

.fade-enter-to {
    opacity: 1;
    transform: scale(1);

}
</style>

小细节:
1.menu菜单属性:collapse折叠

2.如果展示的时候是二级路由的界面,刷新完之后仍不变:使用方法default-active:页面加载时默认激活菜单的 index,他们的index就是路由的路径地址

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值