Vue3+Vite+Ts 项目实战 04 搭建 Layout 布局

2024-08-23 01:08

本文主要是介绍Vue3+Vite+Ts 项目实战 04 搭建 Layout 布局,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Layout 布局容器

<!-- src\layout\AppLayout.vue -->
<template><el-container><el-aside width="200px">Aside</el-aside><el-container><el-header>Header</el-header><el-main><!-- 子路由出口 --><router-view /></el-main></el-container></el-container>
</template><script setup lang="ts"></script><style scoped lang="scss">
.el-container {height: 100vh;
}
.el-header {background-color: #B3C0D1;
}
.el-aside {width: auto;background-color: #304156;
}
.el-main {background-color: #E9EEF3;
}
</style>
// src\styles\common.scss
* {margin: 0;padding: 0;
}
// src\router\index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import AppLayout from '@/layout/AppLayout.vue'const routes:RouteRecordRaw[] = [{path: '/',component: AppLayout,children: [{path: '/',name: 'home',component: () => import('@/views/home/index.vue')}]},{path: '/login',name: 'login',component: () => import('@/views/login/index.vue')}
]const router = createRouter({// history: createWebHashHistory(), // hash 路由模式history: createWebHistory(), // history 路由模式routes // 路由规则
})export default router

配置页面路由导航

初始化路由目录

创建其他几个页面文件(后面可能还会增加):

└─ product # 商品相关├─ attr # 商品规格│   └─ index.vue├─ category # 商品分类│   └─ index.vue└─ list # 商品列表└─ index.vue

配置路由:

// src\router\modules\products.ts
import { RouteRecordRaw, RouterView } from 'vue-router'const routes:RouteRecordRaw = {path: 'product',component: RouterView,children: [{path: 'list',name: 'product_list',component: () => import('@/views/product/list/index.vue')},{path: 'category',name: 'product_category',component: () => import('@/views/product/category/index.vue')},{path: 'attr',name: 'product_attr',component: () => import('@/views/product/attr/index.vue')},{path: 'reply',name: 'product_reply',component: () => import('@/views/product/reply/index.vue')}]
}export default routes
// src\router\index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import AppLayout from '@/layout/AppLayout.vue'
import productRoutes from './modules/product'const routes:RouteRecordRaw[] = [{path: '/',component: AppLayout,children: [{path: '/',name: 'home',component: () => import('@/views/home/index.vue')},productRoutes]},{path: '/login',name: 'login',component: () => import('@/views/login/index.vue')}
]const router = createRouter({// history: createWebHashHistory(), // hash 路由模式history: createWebHistory(), // history 路由模式routes // 路由规则
})export default router

菜单导航

暂时静态编写几个菜单内容:

<!-- src\layout\components\AppMenu.vue -->
<template><el-menuactive-text-color="#ffd04b"background-color="#304156"class="el-menu-vertical-demo"default-active="2"text-color="#fff"router><el-menu-item index="/"><!-- <Menu> 首字母要大写,否则会和浏览器原生的 <menu> 冲突 --><el-icon><Menu /></el-icon><span>首页</span></el-menu-item><el-sub-menu index="1"><template #title><el-icon><location /></el-icon><span>商品</span></template><el-menu-item index="/product/list"><el-icon><Menu /></el-icon><span>商品列表</span></el-menu-item><el-menu-item index="/product/category"><el-icon><Menu /></el-icon><span>商品分类</span></el-menu-item><el-menu-item index="/product/attr"><el-icon><Menu /></el-icon><span>商品规格</span></el-menu-item></el-sub-menu></el-menu>
</template><script setup lang="ts"></script><style scoped></style>
<!-- src\layout\AppLayout.vue -->
<template><el-container><el-aside width="200px"><AppMenu /></el-aside><el-container><el-header>Header</el-header><el-main><!-- 子路由出口 --><router-view /></el-main></el-container></el-container>
</template><script setup lang="ts">
import AppMenu from './AppMenu/index.vue'
</script><style scoped lang="scss">...</style>

切换侧边栏展开收起

存储侧边栏展开状态:

// src\store\index.ts
import { defineStore } from 'pinia'const useStore = defineStore('main', {state: () => ({count: 0,isCollapse: false}),getters: {doubleCount(state) {return state.count * 2}},actions: {increment() {this.count++}}
})export default useStore

创建 Header 布局组件,编写侧边栏控制按钮:

<!-- src\layout\AppHeader\index.vue -->
<template><ToggleSidebar /><!-- 面包屑 -->
</template><script setup lang="ts">
import ToggleSidebar from './ToggleSidebar.vue'
</script><style scoped lang="scss" >
i {font-size: 19px;cursor: pointer;
}
</style>
<!-- src\layout\AppHeader\ToggleSidebar.vue -->
<template><el-icon><component:is="store.isCollapse ? 'expand' : 'fold'"@click="handleCollapse"/></el-icon>
</template><script setup lang="ts">
import useStore from '@/store'const store = useStore()// 因为没有其他地方可以修改侧边栏状态
// 所以这里直接修改
const handleCollapse = () => {store.isCollapse = !store.isCollapse
}
</script><style scoped></style>

绑定侧边栏状态,加载 Header 组件,修改 el-header 样式:

<!-- src\layout\AppLayout.vue -->
<template><el-container><el-aside width="200px"><AppMenu /></el-aside><el-container><el-header><AppHeader /></el-header><el-main><!-- 子路由出口 --><router-view /></el-main></el-container></el-container>
</template><script setup lang="ts">
import AppMenu from './AppMenu/index.vue'
import AppHeader from './AppHeader/index.vue'
</script><style scoped lang="scss">
.el-container {height: 100vh;
}
.el-header {background-color: #fff;color: #333;display: flex;justify-content: space-between;align-items: center;
}
.el-aside {width: auto;background-color: #304156;
}
.el-main {background-color: #E9EEF3;
}
</style>

面包屑导航

通过路由元信息配置路由标题

// src\router\modules\products.ts
import { RouteRecordRaw, RouterView } from 'vue-router'const routes:RouteRecordRaw = {path: 'product',component: RouterView,meta: {title: '商品'},children: [{path: 'list',name: 'product_list',component: () => import('@/views/product/list/index.vue'),meta: {title: '商品列表'}},{path: 'category',name: 'product_category',component: () => import('@/views/product/category/index.vue'),meta: {title: '商品分类'}},{path: 'attr',name: 'product_attr',component: () => import('@/views/product/attr/index.vue'),meta: {title: '商品规格'}}]
}export default routes
// src\router\index.ts
...const routes:RouteRecordRaw[] = [{path: '/',component: AppLayout,children: [{path: '/',name: 'home',component: () => import('@/views/home/index.vue'),meta: {title: '首页'}},...]},...
]...

面包屑组件

<!-- src\layout\AppHeader\Breadcrumb.vue -->
<template><el-breadcrumb separator-icon="arrow-right"><el-breadcrumb-itemv-for="item in routes":key="item.path">{{ item.meta.title }}</el-breadcrumb-item></el-breadcrumb>
</template><script setup lang="ts">
import { useRouter } from 'vue-router'
import { computed } from 'vue'// 获取路由,类似 Vue2 的 this.$router
const router = useRouter()// 获取当前路由的匹配记录
const routes = computed(() => {return router.currentRoute.value.matched.filter(item => item.meta.title)
})</script><style scoped></style>

加载面包屑组件

<!-- src\layout\AppHeader\index.vue -->
<template><el-space size="large"><ToggleSidebar /><Breadcrumb /></el-space>
</template><script setup lang="ts">
import ToggleSidebar from './ToggleSidebar.vue'
import Breadcrumb from './Breadcrumb.vue'
</script><style scoped lang="scss" >
i {font-size: 19px;cursor: pointer;
}
</style>

配置路由元信息 TypeScript 支持,为了方便将自定义创建的类型声明文件放到 src/types 目录下:

// src\types\vue-router.d.ts
import 'vue-router'declare module 'vue-router' {// eslint-disable-next-line no-unused-varsinterface RouteMeta {title?: string}
}

其他

可以使用 nuxt/vue-meta(next 分支) 设置页面标题。

全屏功能

全屏 API - Web API 接口参考 | MDN

创建全屏按钮组件:

<!-- src\layout\AppHeader\FullScreen.vue -->
<template><el-icon><full-screen @click="toggleFullScreen" /></el-icon>
</template><script setup lang="ts">
const toggleFullScreen = () => {if (!document.fullscreenElement) {document.documentElement.requestFullscreen()} else {if (document.exitFullscreen) {document.exitFullscreen()}}
}
</script><style scoped></style>

加载组件

<!-- src\layout\AppHeader\index.vue -->
<template><el-space size="large"><ToggleSidebar /><Breadcrumb /></el-space><el-space size="large"><FullScreen /></el-space>
</template><script setup lang="ts">
import ToggleSidebar from './ToggleSidebar.vue'
import Breadcrumb from './Breadcrumb.vue'
import FullScreen from './FullScreen.vue'
</script><style scoped lang="scss" >
i {font-size: 19px;cursor: pointer;
}
</style>

页面加载进度条

使用 nprogress 实现页面加载进度条效果。

npm i --save nprogress
# TS 类型补充模块
npm i --save-dev @types/nprogress
// src\router\index.ts
...
import nprogress from 'nprogress'
import 'nprogress/nprogress.css'// 关闭 loading 图标
nprogress.configure({ showSpinner: false })...router.beforeEach(() => {// 开始加载进度条nprogress.start()
})router.afterEach(() => {// 结束加载进度条nprogress.done()
})export default router

注意:Vue Router v4.x 开始不建议在导航守卫中使用 next()来调用下一个导航守卫,转而改用 return 来控制,返回 false 会取消当前导航;返回一个路由地址,则会跳转到这个路由;默认路由会调用。

这篇关于Vue3+Vite+Ts 项目实战 04 搭建 Layout 布局的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1097923

相关文章

SpringBoot整合 Quartz实现定时推送实战指南

《SpringBoot整合Quartz实现定时推送实战指南》文章介绍了SpringBoot中使用Quartz动态定时任务和任务持久化实现多条不确定结束时间并提前N分钟推送的方案,本文结合实例代码给大... 目录前言一、Quartz 是什么?1、核心定位:解决什么问题?2、Quartz 核心组件二、使用步骤1

SpringBoot整合AOP及使用案例实战

《SpringBoot整合AOP及使用案例实战》本文详细介绍了SpringAOP中的切入点表达式,重点讲解了execution表达式的语法和用法,通过案例实战,展示了AOP的基本使用、结合自定义注解以... 目录一、 引入依赖二、切入点表达式详解三、案例实战1. AOP基本使用2. AOP结合自定义注解3.

HTML5的input标签的`type`属性值详解和代码示例

《HTML5的input标签的`type`属性值详解和代码示例》HTML5的`input`标签提供了多种`type`属性值,用于创建不同类型的输入控件,满足用户输入的多样化需求,从文本输入、密码输入、... 目录一、引言二、文本类输入类型2.1 text2.2 password2.3 textarea(严格

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)

《JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)》:本文主要介绍如何在IntelliJIDEA2020.1中创建和部署一个JavaWeb项目,包括创建项目、配置Tomcat服务... 目录简介:一、创建项目二、tomcat部署1、将tomcat解压在一个自己找得到路径2、在idea中添加

解决idea启动项目报错java: OutOfMemoryError: insufficient memory

《解决idea启动项目报错java:OutOfMemoryError:insufficientmemory》:本文主要介绍解决idea启动项目报错java:OutOfMemoryError... 目录原因:解决:总结 原因:在Java中遇到OutOfMemoryError: insufficient me

SpringBoot返回文件让前端下载的几种方式

《SpringBoot返回文件让前端下载的几种方式》文章介绍了开发中文件下载的两种常见解决方案,并详细描述了通过后端进行下载的原理和步骤,包括一次性读取到内存和分块写入响应输出流两种方法,此外,还提供... 目录01 背景02 一次性读取到内存,通过响应输出流输出到前端02 将文件流通过循环写入到响应输出流

python项目环境切换的几种实现方式

《python项目环境切换的几种实现方式》本文主要介绍了python项目环境切换的几种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 如何在不同python项目中,安装不同的依赖2. 如何切换到不同项目的工作空间3.创建项目

SpringBoot项目整合Netty启动失败的常见错误总结

《SpringBoot项目整合Netty启动失败的常见错误总结》本文总结了SpringBoot集成Netty时常见的8类问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、端口冲突问题1. Tomcat与Netty端口冲突二、主线程被阻塞问题1. Netty启动阻

python项目打包成docker容器镜像的两种方法实现

《python项目打包成docker容器镜像的两种方法实现》本文介绍两种将Python项目打包为Docker镜像的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录简单版:(一次成功,后续下载对应的软件依赖)第一步:肯定是构建dockerfile,如下:第二步