# 核心內容介紹
-
路由跳轉有兩種方式:
- 聲明式導航:<router-link :to="...">
- 編程式導航:router.push(...) 或?router.replace(...) ;兩者的規則完全一致。
-
push(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>
replace(to: RouteLocationRaw): Promise<NavigationFailure | void | undefined>;
-
- 由于屬性?
to
?與?router.push
?接受的對象種類相同,所以兩者的規則完全相同。
-
路由傳參有兩種方法:
- params:使用動態路由的方式進行傳參;
- 只為了傳參則不建議用params,params 主要是用來進行動態路由匹配的。
- 聲明為動態路由,params則是必傳的!除非設置為可選!
聲明路由時設置該路由props參數為true,則會改變功能形態。(傻逼功能,別用)
- query:拼接在url后面,以?的方式隔開;/urlpath?d1="666"&d2=逆天&arr=["1"]&b=true
- 傳參時僅建議 string | number | (string|number)[] 類型的數據 ,否則編輯器會 ts 報錯提示。
- 所有傳參的數據類型如果非字符串會自動字符串化 >> String(xx)
- params 和 query 的 TS 類型為:string | string[]。也就意味著它并不希望你放亂七八糟的東西在url上,即便你JSON.stringify() 轉換過了。
- params:使用動態路由的方式進行傳參;
-
動態路由:
- 動態路由的跳轉必須是 name + params,用 path 跳轉命名路由將無效;且 params 必傳!
- 動態路由以 `/path1/:id` 的方式進行聲明,跳轉路徑結果為 /path/1
- 動態路由設置的參數例如 :id ,可以將該參數設置為可選參數 `/path1/:id?` ,這樣params就是可傳可不傳了。
-
命名路由:
- 就是聲明了路由的 name。name值是唯一的,不管是頂級路由還是嵌套路由。
- 如果是跳轉嵌套路由里的子路由,path 跳轉需要/xx/xx/child,可直接用該子路由的name。
- 沒有硬編碼的 URL
params
?的自動編碼/解碼。- 防止你在 url 中出現打字錯誤。
- 繞過路徑排序(如顯示一個)
# 說明:
? ? ? ? $route / route:? ??有當前路由的所有信息!
? ? ? ? $router / router:? 用來進行路由操作的!?
?# 聲明路由
-
如何聲明路由
- 必備的 path? component。其他一堆屬性自己了解相關功能就知道什么時候是必要的,什么時候是非必要的了。有用點的就是name??redirect? children? meta了。
-
頂級路由
- 最外層的路由
-
嵌套路由
- 聲明路由的 children?
- 嵌套路由不限層級
- 想要默認加載一個子路由的話將path設置為空字符串:` path:"" `。
- 跳轉嵌套路由最好使用 name 方式跳轉,降低心智負擔!
-
聲明為動態路由,上面講過了,忘了?別怕,那下面代碼也有示例。
-
路由重定向
-
redirect: { name: 'routeName' }, 設置為路由的name最保險,別想著其他花里胡哨的。
-
在寫?redirect 的時候,如果不是嵌套路由,可以省略?component 配置。
你重定向到自己的子路由,那肯定要有?component ?啊,不然你 router-view 在哪(笑)
-
-
命名視圖
-
component 變 components,具體看代碼
-
-
本示例包含 path , name ,? meta , component , components , children ,? redirect , props , 路由懶加載 , alias 。
import { createRouter, createWebHistory } from 'vue-router'export const router = createRouter({history: createWebHistory(), // 設置路由模式routes: [{// 普通的設置一個普通的路由(頂級路由)path: '/',name: 'HelloWorld',meta: { requiresXXX: true }, // 設置路由元信息,應用場景的話:主要就路由守衛里用的會多一點。該數據只能在這里聲明,其他途徑無法修改。component: () => import('../components/HelloWorld.vue') // 設置路由懶加載},{path: '/routerVue/:id', // 設置為動態路由,id則必傳// path: '/routerVue/:id?', // 設置該動態路由的 id 為可選參數,變為非必傳name: 'routerVue',component: () => import('@/components/xxx.vue')},{path: '/demo',alias: '/hellow', // 你訪問 /hellow,頁面url路徑會保持為/hellow,但是路由匹配則為/demo,顯示 yyyyyy.vue 組件內容component: () => import('@/components/yyyyyy.vue')},{path: '/edit:id?',name: 'edit',// redirect: { name: 'profile' }, // 路由重定向,訪問 /edit 直接重定向為 /edit/profilecomponent: () => import('../components/edit.vue'),props: true, // 設置為true 則在路由組件中,動態路由的參數 會直接放在vue的 props 里。 // 完全不推薦的寫法,增加心智負擔。children: [ // 設置為嵌套路由{// 當 /edit 匹配成功// demo2.vue 將被渲染到 edit 的 <router-view> 內部path: '', // 路徑為'',需要增加name,不然會拋出警告。component: () => import('../components/demo2.vue'),// 命名視圖功能: component 變為 components ,然后設置對應視圖組件的名稱// components:{ // 注意加 s 。。。// default: () => import('../components/router-test1.vue'),// template1: () => import('../components/router-test2.vue'),// },// props: {default: true , template1: false} // 可以為每個命名視圖定義 props 配置。還可設置為函數模式(超不推薦,提高代碼維護理解難度,對功能方面沒任何提升)},{// 當 /edit/profile 匹配成功// demo.vue 將被渲染到 edit 的 <router-view> 內部path: 'profile',name: 'profile',component: () => import('../components/profile.vue'),}]},{// 匹配所有路徑,當上述路徑都不滿足時,跳轉到404頁面// 如果項目是有動態添加路由的,注意一定要把該404路由提取出來,等動態添加完路由,再把404添加到動態路由的最后一個。path: '*',name: '404',component: () => import('../components/404.vue'),},],
})
?# 路由跳轉的多種寫法:
聲明式導航寫法:
<router-link :to="{ name: 'vue33', params: { id: 110 }, query: { d1: 'wuwu~~~' } }">vue3.3/3.4新特性</router-link>
編程式導航寫法:(options api里的方式)
this.$router.push({name: 'vue33',params: {id: 110},query: {data: 666}
})
編程式導航寫法:(composition api里的方式)
import { useRouter } from 'vue-router'
let router = useRouter()
function tiaozhuan() {router.push({name: 'vue33',params: {id: 110},query: {data: 666}})
}
replace 是當前頁面替換新頁面,路由歷史記錄里不會保存當前頁。
import { useRouter } from 'vue-router'
let router = useRouter()
function tiaozhuan() {router.replace({name: 'vue33',params: {id: 110},query: {data: 666}})
}
如果是嵌套路由則是父路由path + 子路由path,或者子路由的name,并且跳轉時,如果父路由是命名路由,則params也會是必傳!
# 獲取路由參數
跳轉目標路由,聲明了params或query之后,(選項式api寫法) 通過this.$route.params 或 this.$route.query 即可拿到對應的路由參數;
組合式API寫法如下:
import { useRoute } from 'vue-router'let route = useRoute()console.log(route.params);
console.log(route.query);
console.log(route.meta);
# 重新提醒:
route:??有當前路由的所有信息
router: 用來進行路由操作的!?
# 路由的導航守衛
- 全局守衛;
- beforeEach :全局前置守衛? (1)
- beforeResolve?:全局解析守衛? (3)
- afterEach:全局后置鉤子,該鉤子在已經進入該路由后觸發,所以無需return true 或 next()。? (4)
- 路由獨享的守衛:
- beforeEnter :在所有組件內守衛和異步路由組件被解析之后調用。(2)
-
組件守衛:有3個,其中2個沒屁用。
-
beforeRouteEnter :能處理的 beforeEnter 都可以。
-
beforeRouteUpdate :更沒必要,直接 watch route.params 即可。
-
beforeRouteLeave :有點用,如果用戶跳轉路由時,當前頁面編輯內容未保存,則可以 return false 取消路由跳轉。(setup 內則手動引入 onBeforeRouteLeave)
-
-
觸發順序(1)(2)(3)(4)。
-
組件守衛其中2個懶得算,如果算上 beforeRouteLeave 那 beforeRouteLeave 排在beforeEach 前面。
-
每個守衛方法接收兩個參數:
- to:? ? ? 即將要進入的目標 。
- from:? 當前導航正要離開的路由 。
- next:? 可選的第三個參數 。(現在根據return 結果來決定了,且更安全(確保調用一次),所以基本不需要next了)
import { createRouter } from 'vue-router'
const router = createRouter({ ... })router.beforeEach((to, from) => {// ...return false // 返回 false 以取消導航// 如果什么都沒有,undefined 或返回 true,則導航是有效的,并調用下一個導航守衛// return { name: 'Login' } // 將用戶重定向到登錄頁面
})
# 動態添加路由
應用場景示例:頁面菜單和所擁有的路由是根據用戶角色動態生成的,此時就需要配合addRoute功能來實現需求。
//! 動態添加路由、刪除路由、添加嵌套路由
router.addRoute({ path: '/about', component: xxx })// 當路由被刪除時,所有的別名和子路由也會被同時刪除
// 會返回一個回調,調用該函數即可刪除路由 (這種方式可以保證刪的更準點吧。。。)
const removeRoute = router.addRoute({ path: '/about', component: xxx })
removeRoute()
// router.removeRoute('about') 通過路由名稱進行刪除,路由表有同名的話需要注意點(建議路由表name都是唯一的!)// 添加嵌套路由
// router.addRoute({ name: 'admin', path: '/admin', component: Admin })
// router.addRoute('admin', { path: 'settings', component: AdminSettings })
//> 上述代碼等同如如下:
// router.addRoute({
// name: 'admin',
// path: '/admin',
// component: Admin,
// children: [{ path: 'settings', component: AdminSettings }],
// })
# 查看現有路由?
Vue Router 提供了兩個功能來查看現有的路由:
- router.hasRoute():檢查路由是否存在。
- router.getRoutes():獲取一個包含所有路由記錄的數組。
# 路由緩存、過渡
<router-view>、<keep-alive>?和?<transition>?
transition?和?keep-alive?現在必須通過?v-slot?API 在?RouterView?內部使用:
<router-view v-slot="{ Component }"><transition><keep-alive><component :is="Component" /></keep-alive></transition>
</router-view>
# 路由模式
- Hash 模式:createWebHashHistory
- HTML5 模式:createWebHistory
import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({history: createWebHashHistory(),routes: [//...],
})
html5模式需要在服務器上設置初次訪問如果404時,進行路由回退:
nginx 如下:
location / {try_files $uri $uri/ /index.html;
}
其他的詳見官網;