레이아웃 레이아웃 컨테이너
<!-- 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-menu
active-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
헤더 레이아웃 구성 요소를 만들고 사이드바 컨트롤 버튼을 작성합니다.
<!-- 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>
사이드바 상태를 바인딩하고 헤더 구성 요소를 로드하고 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-item
v-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-vars
interface RouteMeta {
title?: string
}
}
다른
페이지 제목은 nuxt/vue-meta(다음 분기)를 사용하여 설정할 수 있습니다 .
전체 화면 기능
전체 화면 API - 웹 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 라우터 v4.x
next()
부터는 탐색 가드에서 다음 탐색 가드를 호출하는 데 사용하지 않는 것이 좋습니다 . 대신return
제어에 사용하고 반환하면false
현재 탐색이 취소됩니다. 라우팅 주소를 반환하면 이 위치로 점프합니다. 기본 경로가 호출됩니다.