>[success] # 路由守衛
* 從路由`4.x` 開始已經可以不使用`next` 參數 以前使用`next` 參數需要注意調用次數
~~~
// BAD
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
// 如果用戶未能驗證身份,則 `next` 會被調用兩次
next()
})
~~~
~~~
// GOOD
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
~~~
* 從`4.x` 開始只要去指定返回值即可對應跳轉路由
* * 1.false: 不進行導航
* * 2.undefined或者不寫返回值和返回值為`true`: 進行默認導航
* * 3.字符串: 路徑, 跳轉到對應的路徑中
* * 4.對象: 類似于 router.push({path: "/login", query: ....})
~~~
router.beforeEach((to) => {
console.log(to.path)
if (to.path === '/home') {
return { path: '/about', query: { age: '123' } } // 可以不在使用next形式
}
})
~~~
>[info] ## 關于路由守衛
1. `vuerouter` 一套鉤子來觸發路由在不同階段觸發的函數
2. 導航守衛分成三大塊**全局守衛,路由獨享守衛,組件內守衛**
* **全局守衛**顧名思義所有路由在進入跳轉的時候都會觸發,整個全局守衛分為三個階段依次是`beforeEach`、`beforeResolve`、`afterEach`
* **路由獨享守衛**,只在定義路由中使用它有一個階段`beforeEnter`
* **組件內守衛**,只在組件中觸發的路由內容它有三個階段依次`beforeRouteEnter`、`beforeRouteUpdate`、`beforeRouteLeave`
3. 關于守衛中回調參數
* to: Route: 即將要進入的目標 路由對象
* from: Route: 當前導航正要離開的路由
>[danger] ##### 全局守衛 -- 全局前置守衛(beforeEach)
1. **全局前置守衛**在路由剛開始觸發且還未進入,路由對應的組件中,簡單的理解最早觸發,但是觸發時候沒有任何組件一類的加載,正因為如此適合做登陸判斷邏輯
~~~
const router = createRouter({ ... })
router.beforeEach(async (to, from) => {
if (
// 檢查用戶是否已登錄
!isAuthenticated &&
// ?? 避免無限重定向
to.name !== 'Login'
) {
// 將用戶重定向到登錄頁面
return { name: 'Login' }
}
})
~~~
* 在router 3.x 時候一般是這么寫現在不推薦了
~~~
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
~~~
>[danger] ##### 全局守衛 -- 全局解析守衛(beforeResolve )
1. 在導航被確認之前,同時在路由獨享守衛和所有組件內守衛和異步路由組件被解析之后,解析守衛就被調用,實際開發中沒太用過
>[danger] ##### 全局守衛 -- 全局后置鉤子(afterEach)
1. 在所有路由的生命周期結束后調用,使用場景它們對于分析、更改頁面標題、聲明頁面等輔助功能以及許多其他事情都很有用。或者當我們在加載后臺數據的時候經常會做一個蒙版這個蒙版上會有一個加載的轉圈的團,`afterEach`是整個路由結束階段,因此也可以理解成是整個組件加載完階段,所以在這個時候控制蒙版消失最好
>[danger] ##### 路由獨享守衛 -- beforeEnter
1. `beforeEnter`守衛**只在進入路由時觸發**,不會在`params`、`query`或`hash`改變時觸發。例如,從`/users/2`進入到`/users/3`或者從`/users/2#info`進入到`/users/2#projects`。它們只有在**從一個不同的**路由導航時,才會被觸發。
~~~
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
// reject the navigation
return false
},
},
]
~~~
* 除了支持函數也支持數組的形式
~~~
function removeQueryParams(to) {
if (Object.keys(to.query).length)
return { path: to.path, query: {}, hash: to.hash }
}
function removeHash(to) {
if (to.hash) return { path: to.path, query: to.query, hash: '' }
}
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: [removeQueryParams, removeHash],
},
{
path: '/about',
component: UserDetails,
beforeEnter: [removeQueryParams],
},
]
~~~
>[info] ## 組件路由守衛
~~~
const UserDetails = {
template: `...`,
beforeRouteEnter(to, from) {
// 在渲染該組件的對應路由被驗證前調用
// 不能獲取組件實例 `this` !
// 因為當守衛執行時,組件實例還沒被創建!
},
beforeRouteUpdate(to, from) {
// 在當前路由改變,但是該組件被復用時調用
// 舉例來說,對于一個帶有動態參數的路徑 `/users/:id`,在 `/users/1` 和 `/users/2` 之間跳轉的時候,
// 由于會渲染同樣的 `UserDetails` 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。
// 因為在這種情況發生的時候,組件已經掛載好了,導航守衛可以訪問組件實例 `this`
},
beforeRouteLeave(to, from) {
// 在導航離開渲染該組件的對應路由時調用
// 與 `beforeRouteUpdate` 一樣,它可以訪問組件實例 `this`
},
}
~~~
~~~
1.可以通過傳一個回調給 next來訪問組件實例。在導航被確認的時候執行回
調,并且把組件實例作為回調方法的參數。
2.注意 beforeRouteEnter 是支持給 next 傳遞回調的唯一守衛。對于
beforeRouteUpdate 和 beforeRouteLeave 來說,this 已經可用了,所以不
支持傳遞回調,因為沒有必要了。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通過 `vm` 訪問組件實例
})
}
~~~
1. **導航完成之后獲取**:先完成導航,然后在接下來的組件生命周期鉤子中獲取數據。在數據獲取期間顯示“加載中”之類的指示。
2. 在**導航完成之前獲取**:導航完成前,在路由進入的守衛中獲取數據,在數據獲取成功后執行導航
也就是說你可以選擇在vue 生命周期中獲取請求接口數據,也可以在組件的路由生命周期去獲取數據這完全是看個人習慣 [鏈接](https://router.vuejs.org/zh/guide/advanced/data-fetching.html#%E5%9C%A8%E5%AF%BC%E8%88%AA%E5%AE%8C%E6%88%90%E5%89%8D%E8%8E%B7%E5%8F%96%E6%95%B0%E6%8D%AE)
>[info] ## 路由組件完整周期
1. 導航被觸發。
2. 在失活的組件里調用`beforeRouteLeave`守衛。
3. 調用全局的`beforeEach`守衛。
4. 在重用的組件里調用`beforeRouteUpdate`守衛(2.2+)。
5. 在路由配置里調用`beforeEnter`。
6. 解析異步路由組件。
7. 在被激活的組件里調用`beforeRouteEnter`。
8. 調用全局的`beforeResolve`守衛(2.5+)。
9. 導航被確認。
10. 調用全局的`afterEach`鉤子。
11. 觸發 DOM 更新。
12. 調用`beforeRouteEnter`守衛中傳給`next`的回調函數,創建好的組件實例會作為回調函數的參數傳入。
- 官網給的工具
- 聲明vue2 和 vue3
- 指令速覽
- Mustache -- 語法
- v-once -- 只渲染一次
- v-text -- 插入文本
- v-html -- 渲染html
- v-pre -- 顯示原始的Mustache標簽
- v-cloak -- 遮蓋
- v-memo(新)-- 緩存指定值
- v-if/v-show -- 條件渲染
- v-for -- 循環
- v-bind -- 知識
- v-bind -- 修飾符
- v-on -- 點擊事件
- v-model -- 雙向綁定
- 其他基礎知識速覽
- 快速使用
- 常識知識點
- key -- 作用 (后續要更新)
- computed -- 計算屬性
- watch -- 偵聽
- 防抖和節流
- vue3 -- 生命周期
- vue-cli 和 vite 項目搭建方法
- vite -- 導入動態圖片
- 組件
- 單文件組件 -- SFC
- 組件通信 -- porp
- 組件通信 -- $emit
- 組件通信 -- Provide / Inject
- 組件通信 -- 全局事件總線mitt庫
- 插槽 -- slot
- 整體使用案例
- 動態組件 -- is
- keep-alive
- 分包 -- 異步組價
- mixin -- 混入
- v-model-- 組件
- 使用計算屬性
- v-model -- 自定義修飾符
- Suspense -- 實驗屬性
- Teleport -- 指定掛載
- 組件實例 -- $ 屬性
- Option API VS Composition API
- Setup -- 組合API 入口
- api -- reactive
- api -- ref
- 使用ref 和 reactive 場景
- api -- toRefs 和 toRef
- api -- readonly
- 判斷性 -- API
- 功能性 -- API
- api -- computed
- api -- $ref 使用
- api -- 生命周期
- Provide 和 Inject
- watch
- watchEffect
- watch vs. watchEffect
- 簡單使用composition Api
- 響應性語法糖
- css -- 功能
- 修改css -- :deep() 和 var
- Vue3.2 -- 語法
- ts -- vscode 配置
- attrs/emit/props/expose/slots -- 使用
- props -- defineProps
- props -- defineProps Ts
- emit -- defineEmits
- emit -- defineEmits Ts
- $ref -- defineExpose
- slots/attrs -- useSlots() 和 useAttrs()
- 自定義指令
- Vue -- 插件
- Vue2.x 和 Vue3.x 不同點
- $children -- 移除
- v-for 和 ref
- attribute 強制行為
- 按鍵修飾符
- v-if 和 v-for 優先級
- 組件使用 v-model -- 非兼容
- 組件
- h -- 函數
- jsx -- 編寫
- Vue -- Router
- 了解路由和vue搭配
- vueRouter -- 簡單實現
- 安裝即使用
- 路由懶加載
- router-view
- router-link
- 路由匹配規則
- 404 頁面配置
- 路由嵌套
- 路由組件傳參
- 路由重定向和別名
- 路由跳轉方法
- 命名路由
- 命名視圖
- Composition API
- 路由守衛
- 路由元信息
- 路由其他方法 -- 添加/刪除/獲取
- 服務器配置映射
- 其他
- Vuex -- 狀態管理
- Option Api -- VUEX
- composition API -- VUEX
- module -- VUEX
- 刷新后vuex 數據同步
- 小技巧
- Pinia -- 狀態管理
- 開始使用
- pinia -- state
- pinia -- getter
- pinia -- action
- pinia -- 插件 ??
- Vue 源碼解讀
- 開發感悟
- 練手項目