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

相关文章

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

Vue和React受控组件的区别小结

《Vue和React受控组件的区别小结》本文主要介绍了Vue和React受控组件的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录背景React 的实现vue3 的实现写法一:直接修改事件参数写法二:通过ref引用 DOMVu

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同