第十五章:配置 vue-router

安裝

pnpm add vue-router@4

一、創(chuàng)建路由配置

1.1、創(chuàng)建 src/router/routes/index.ts 文件,并進行路由配置

// src/router/routes/index.ts

import type { RouteRecordRaw } from 'vue-router'
import { DashboardOutlined, HomeOutlined } from '@ant-design/icons-vue'
import { LOGIN_NAME, PAGE_NOT_FOUND_NAME } from '../constant'

export const routesList: Array<RouteRecordRaw> = [
    {
        path: '/',
        name: 'Layout',
        redirect: '/dashboard/welcome',
        component: () => import('@/layout/layout.vue'), // 需要創(chuàng)建 src/layout/layout.vue 文件否則會報錯
        meta: {
            title: '首頁',
            fullPath: '/',
        },
        children: [
            {
                 path: '/dashboard',
                 name: 'Dashboard',
                 redirect: '/dashboard/welcome',
                 meta: {
                     title: '概覽頁',
                     fullPath: '/dashboard',
                     icon: DashboardOutlined,
                 },
                 children: [
                     {
                         path: 'welcome',
                         name: 'DashboardWelcome',
                         meta: {
                             title: '工作臺',
                             fullPath: '/dashboard/welcome',
                             icon: HomeOutlined,
                         },
                         component: () => import('@/views/dashboard/welcome/welcome.vue'), // 需要創(chuàng)建 src/views/dashboard/welcome/welcome.vue 文件否則會報錯
                     },
                 ],
            },
            {
                path: '/account',
                redirect: '/account/settings',
                name: 'Account',
                meta: {
                    title: '個人中心',
                    fullPath: '/account',
                    hideInMenu: true,
                },
               children: [
                   {
                        path: 'settings',
                        name: 'AccountSettings',
                        component: () => import('@/views/account/settings/settings.vue'),
                        meta: {
                            title: '個人設(shè)置',
                            fullPath: '/account/settings',
                        },
                   },
               ],
            },
        ],
    },
    {
        path: '/login',
        name: LOGIN_NAME,
        component: () => import('@/views/login/login.vue'),
        meta: {
            title: '登錄',
        },
    },
    {
        path: '/:pathMatch(.*)*', // 捕獲所有路由或 404 Not found 路由
        name: PAGE_NOT_FOUND_NAME,
        meta: {
            title: '404 Not found',
        },
        component: () => import('@/views/error/404.vue'), // 需要創(chuàng)建 src/views/error/404.vue 文件否則會報錯
    }

];

1.2、創(chuàng)建 types/vue-router.d.ts 自定義路由配置項 meta: RouteMeta 的類型聲明

// types/vue-router.d.ts

import type { RouteMeta as VRouteMeta } from 'vue-router'

declare module 'vue-router' {
    interface RouteMeta extends VRouteMeta {
        /** 標題 */
        title: string;

        /** 當前路由所在的完整路徑, 用來實現(xiàn)登錄后的重定向功能 */
        fullPath: string

        /** 
         * 菜單圖標; antd 圖標名稱, 這是臨時寫法
         * TODO: 后期還要根據(jù) antd icon 中提供的方法,進行自定義一些圖標,但是需要注意的是,自定義圖標后需要驗證側(cè)邊欄菜單中的圖標是否還能正常展示
         * 例如: antd 圖標為 <StepBackwardOutlined />,那么 icon 屬性的值則是:StepBackwardOutlined
         */
        icon?: any;

        /** 是否需要緩存 */
        keepAlive?: boolean

        /** 是否外鏈 */
        isExt?: boolean

        /**
         * 外鏈打開方式
         * 1: 新窗口打開
         * 2: 內(nèi)嵌 iframe
         */
        extOpenMode?: 1 | 2

         /** 是否隱藏頁面加載進度條 */
        hideProgressBar?: boolean;

        /**
         * 不在菜單中顯示
         * 此屬性只會控制側(cè)邊欄中的一級菜單是否展示,不會對子級菜單的是否展示進行控制
         * 如果要對子級菜單進行控制,請使用 hideChildrenInMenu 屬性
         */
        hideInMenu?: boolean

        /**
         * 在菜單中隱藏子節(jié)點, 一般在 children 中有隱藏的子節(jié)點時,可以設(shè)置 hideChildrenInMenu: true 來只顯示父級菜單名稱
         * 例如: 父級菜單: 用戶列表頁 (/user/list) 路由配置中可以設(shè)置 hideChildrenInMenu: true,
         * 例如: 子級菜單: 用戶詳情頁 (/user/list/1, /user/list/2, /user/list/3) 不會出現(xiàn)在菜單中
         */
        hideChildrenInMenu?: boolean

        /** 不在頁面 header 中的面包屑導航中顯示 */
        hideInBreadcrumb?: boolean

        /** 不在tab標簽頁中顯示 */
        hideInTabs?: boolean

       
    }
}

1.3、創(chuàng)建 src/layout/layout.vue 文件

// src/layout/layout.vue

<script setup>

</script>

<template>
  <div class="mt-12px">layout/layout.vue</div>
  <router-view />
</template>

<style scoped>

</style>

1.4、創(chuàng)建 src/views/dashboard/welcome/welcome.vue 文件

// src/views/dashboard/welcome/welcome.vue

<script setup>

</script>

<template>
  <div class="mt-12px">
     工作臺
 </div>
</template>

<style scoped>

</style>

1.5、創(chuàng)建 src/views/login/login.vue 文件

// src/views/login/login.vue

<script setup lang="ts">
import { message } from 'ant-design-vue'
import { ref } from 'vue'

const loading = ref(false)
const loginFormModel = ref({
    username: 'admin',
    password: 'a123456',
})

const handleSubmit = async () => {
    const { username, password } = loginFormModel.value
    if (username.trim() === '' || password.trim() === '') {
        return message.warning('用戶名或密碼不能為空!')
    }
     message.loading('登錄中...', 0)
     loading.value = true
}
</script>

<template>
    <div class="login-box">
        <div class="login-logo">
            <img src="~@/assets/logo.svg" width="45">
            <h1 class="mb-0 ml-2 text-3xl font-bold">
                后臺管理系統(tǒng)
            </h1>
        </div>

        <a-form layout="horizontal" :model="loginFormModel" @submit.prevent="handleSubmit">
            <a-form-item>
                <a-input v-model:value="loginFormModel.username" size="large" placeholder="admin">
                    <template #prefix>
                        <Icon icon="ant-design:user-outlined" />
                    </template>
                </a-input>
            </a-form-item>

            <a-form-item>
                <a-input
                    v-model:value="loginFormModel.password"
                    size="large"
                    type="password"
                    placeholder="a123456"
                    autocomplete="new-password"
                >
                    <template #prefix>
                        <Icon icon="ant-design:lock-outlined" />
                    </template>
                </a-input>
            </a-form-item>

            <a-form-item>
                <a-button type="primary" html-type="submit" size="large" :loading="loading" block>
                    登錄
                </a-button>
            </a-form-item>
        </a-form>
    </div>
</template>

<style lang="less" scoped>
.login-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100vw;
    height: 100vh;
    padding-top: 240px;
    background: #fff;
    background-size: 100%;

    .login-logo {
        display: flex;
        align-items: center;
        margin-bottom: 30px;
    }

    :deep(.ant-form) {
        width: 400px;

        .ant-col {
            width: 100%;
        }

        .ant-form-item-label {
            padding-right: 6px;
        }
    }
}
</style>

1.6、創(chuàng)建 src/views/error/404.vue 文件

// src/views/error/404.vue

<script setup>

</script>

<template>
  <div class="mt-12px">src/views/error/404.vue</div>
</template>

<style scoped>

</style>

二、創(chuàng)建路由實例

2.1、創(chuàng)建 src/router/index.ts 文件,并進行實例化路由器

// src/router/index.ts

import type { App } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { routesList } from './routes'

export const router = createRouter({
    // import.meta.env.BASE_URL
    history: createWebHashHistory(import.meta.env.BASE_URL),
    routes: routesList, // 將 1.1 中創(chuàng)建好的路由配置引入到這里
});

// 通過 setupRouter 函數(shù)將 router 實例傳遞給 app 應(yīng)用
export async function setupRouter(app: App) {

    app.use(router)

     // 路由準備就緒后,路由插件幫我們做了如下操作:
    // 1、全局注冊 RouterView 和 RouterLink 組件。
    // 2、添加全局 $router 和 $route 屬性(可以在組件模板中使用)
    // 3、啟用 useRouter() 和 useRoute() 組合式函數(shù)。
    // 4、觸發(fā)路由器解析初始路由。
    await router.isReady()
}

export default router;

三、注冊路由器插件(在 src/main.ts 中)

// src/main.ts

import { createApp } from 'vue'
const app = createApp(App)

// 掛載路由
async function setupAppRouter() {
  await setupRouter(app)

  // 路由準備就緒后才能掛載APP實例
  app.mount('#app')
}

setupAppRouter()

四、添加路由出口(在 src/App.vue 中)

// src/App.vue

<template>
    <!-- 采用 RouterView 插槽的方式設(shè)置路由出口,便于擴展其它功能 -->
    <router-view v-slot="{ Component }">
         <component :is="Component" />
    </router-view>
</template>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容