[Toc]
>[success] # 導航守衛
~~~
1.vuerouter 一套鉤子來觸發路由在不同階段觸發的函數
2.導航守衛分成三大塊'全局守衛','路由獨享守衛','組件內守衛'
3.'全局守衛' 顧名思義所有路由在進入跳轉的時候都會觸發,整個'全局路
由'分為三個階段依次是'beforeEach'、'beforeResolve'、'afterEach'
4.'路由獨享守衛' 顧名思義只在定義路由和路由組件中的對象中使用它有一
個階段'beforeEnter'
5.'組件內守衛'顧名思義只在組件中觸發的路由內容它有三個階段依次
是'beforeRouteEnter'、'beforeRouteUpdate'、'beforeRouteLeave'
~~~
>[info] ## 導航守衛中三個參數講解
~~~
1.to和from 都是route的對象,因此可以使用route中獲取路由參數的所有方
法,官方api'https://router.vuejs.org/zh/api/#%E8%B7%AF%E7%94%B1%E5%AF%B9%E8%B1%A1'
2.next 是跳轉下一個守衛用的,也可以指定守衛,可用的參數和router-link
中的to一致的
3.官方的具體講解:
to: Route: 即將要進入的目標 路由對象
from: Route: 當前導航正要離開的路由
next: Function: 一定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。
next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到 from 路由對應的地址。
next('/') 或者 next({ path: '/' }): 跳轉到一個不同的地址。當前的導航被中斷,然后進行一個新的導航。你可以向 next 傳遞任意位置對象,且允許設置諸如 replace: true、name: 'home' 之類的選項以及任何用在 router-link 的 to prop 或 router.push 中的選項。
next(error): (2.4.0+) 如果傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 注冊過的回調。
~~~
>[info] ## 全局守衛
~~~
1.全局守衛因為可以監聽到所有路由,在觸發的時候可以用來做判斷用戶是
否登錄,這種全局配置
2.'beforeEach' -- 官方給的中文名字叫'全局前置守衛'在路由剛開始觸發且還
未進入,路由對應的組件中,簡單的理解最早觸發,但是觸發時候沒有任何
組件一類的加載,正因為如此適合做登陸判斷邏輯。
3.'beforeResolve'在導航被確認之前,同時在路由獨享守衛和所有組件內守衛和異步路由組件被解析之后,解析守衛就被調用
4.'afterEach' 在所有路由的生命周期結束后調用,簡單的說就是整個路由周
期都完事了,這個階段可以做一場景,當我們在加載后臺數據的時候經常會做一個蒙
版這個蒙版上會有一個加載的轉圈的團,'afterEach'是整個路由結束階段,因此也可以
理解成是整個組件加載完階段,所以在這個時候控制蒙版消失最好
~~~
>[danger] ##### 案例
~~~
1.下面代碼執行 完后打印的數據順序:
beforeEach 生命周期
beforeResolve 生命周期
afterEach 生命周期
2.要注意是'afterEach ' 整個生命周期都已經結束了,所以不需要在使用
next()往下繼續傳遞執行了。
~~~
~~~
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to='/app/123'>sapp</router-link>
<router-link to='/app/456'>sapp</router-link>
<router-view></router-view>
</div>
<template id="sapp">
<div>
{{$route.params.id}}
</div>
</template>
<script type="text/javascript">
const sapp = {
template:'#sapp',
};
const routes=[
{
path:"/app/:id",
component:sapp,
},
];
const router = new VueRouter({
routes // (縮寫) 相當于 routes: routes
});
// 驗證用戶登錄
router.beforeEach((to, from, next)=>{
console.log('beforeEach 生命周期');
//next('/login') 接受的參數和router-link一致
next();
});
router.beforeResolve((to, from, next)=>{
console.log('beforeResolve 生命周期');
next()
});
// 跳轉之后執行 沒有next
router.afterEach((to, from)=>{
console.log('afterEach 生命周期');
});
var vms = new Vue({
el: "#app",
router,
})
</script>
</body>
</html>
~~~
>[info] ## 路由獨享守衛
~~~
1.路由獨享守衛 中只有'路由獨享守衛' -- 'beforeEnter' 階段,是當前組件路
由進入的時候觸發的階段
~~~
>[danger] ##### 案例
~~~
1.下面案例觸發順序展示的是全局守衛和路由守衛整體的生命周期:
beforeEach 生命周期
beforeEnter 路由中的路由
beforeResolve 生命周期
afterEach 生命周期
~~~
~~~
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to='/app/123'>sapp</router-link>
<router-link to='/app/456'>sapp</router-link>
<router-view></router-view>
</div>
<template id="sapp">
<div>
{{$route.params.id}}
</div>
</template>
<script type="text/javascript">
const sapp = {
template:'#sapp',
};
const routes=[
{
path:"/app/:id",
component:sapp,
beforeEnter(to, from, next){
console.log('beforeEnter 路由中的路由');
next();
}
},
];
const router = new VueRouter({
routes // (縮寫) 相當于 routes: routes
});
// 驗證用戶登錄
router.beforeEach((to, from, next)=>{
console.log('beforeEach 生命周期');
//next('/login') 接受的參數和router-link一致
next();
});
router.beforeResolve((to, from, next)=>{
console.log('beforeResolve 生命周期');
next()
});
// 跳轉之后執行 沒有next
router.afterEach((to, from)=>{
console.log('afterEach 生命周期');
});
var vms = new Vue({
el: "#app",
router,
})
</script>
</body>
</html>
~~~
>[info] ## 組件內的守衛
~~~
1.組件內守衛分三個階段:
'beforeRouteEnter'、'beforeRouteUpdate'、'beforeRouteLeave'三個階段會在不同時刻觸發
2.'beforeRouteEnter' 在還沒有進入該組件之前觸發,一般用獲取異步請求
,可以替代vue生命周期中獲取數據請求
3.'beforeRouteUpdate'在動態路由中使用,由于動態路由中切換路由的時候
,猶豫綁定的是同一個組件因此在不會在重新渲染,但是為了可以讓組件中
的內容重新渲染,有兩種方法第一種使用watch 監聽,但這種需要使
用'props'寫法,另一種就是在'beforeRouteUpdate' 它會監聽到動態路由的改
變,因此可以在這個周期中異步動態路由對應的數據
4.'beforeRouteLeave' 離開組件的時候觸發,可以對表單一些校驗未提交的
時候觸發詢問用戶是否到下一個頁面官方的說法這個離開守衛通常用來禁止
用戶在還未保存修改前突然離開。該導航可以通過 next(false) 來取消。
~~~
>[danger] ##### 官方對組件守衛的特殊說明
~~~
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應路由被 confirm 前調用
// 不!能!獲取組件實例 `this`
// 因為當守衛執行前,組件實例還沒被創建
},
beforeRouteUpdate (to, from, next) {
// 在當前路由改變,但是該組件被復用時調用
// 舉例來說,對于一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
// 由于會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。
// 可以訪問組件實例 `this`
},
beforeRouteLeave (to, from, next) {
// 導航離開該組件的對應路由時調用
// 可以訪問組件實例 `this`
}
}
~~~
* 想利用 'beforeRouteEnter ' 特性給組件獲取異步值
~~~
1.可以通過傳一個回調給 next來訪問組件實例。在導航被確認的時候執行回
調,并且把組件實例作為回調方法的參數。
2.注意 beforeRouteEnter 是支持給 next 傳遞回調的唯一守衛。對于
beforeRouteUpdate 和 beforeRouteLeave 來說,this 已經可用了,所以不
支持傳遞回調,因為沒有必要了。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通過 `vm` 訪問組件實例
})
}
~~~
>[danger] ##### 案例
~~~
1.下面案例中當點擊左側sapp連接的生命周期如下:
'beforeEach 生命周期'
'beforeEnter 路由中的路由'
'beforeRouteEnter 組件中的路由'
'beforeResolve 生命周期'
'afterEach 生命周期'
2.點擊完左側在點擊右側sapp的生命周期,不會在觸發路由的守衛:
'beforeEach 生命周期'
'beforeRouteUpdate 組件中的路由'
'beforeResolve 生命周期'
'afterEach 生命周期'
3.點擊test先觸發組件離開的守衛在依次觸發全局守衛:
'beforeRouteLeave 組件中的路由'
'beforeEach 生命周期'
'test -- beforeEnter 路由中的路由'
'test -- beforeRouteEnter 組件中的路由'
'beforeResolve 生命周期'
'afterEach 生命周期'
~~~
~~~
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to='/app/123'>sapp</router-link>
<router-link to='/app/456'>sapp</router-link>
<router-link to='/test'>test</router-link>
<router-view></router-view>
</div>
<template id="sapp">
<div>
{{$route.params.id}}
</div>
</template>
<script type="text/javascript">
const sapp = {
// 獲取輸出,在路由觸發前獲取數據,但是此時獲取不到路由的this對象
beforeRouteEnter(to, from, next){
console.log('beforeRouteEnter 組件中的路由');
//next();
next(vm=>{
console.log(vm)
})
},
// 同一個組件不同路由觸發
beforeRouteUpdate(to, from, next){
console.log('beforeRouteUpdate 組件中的路由')
next()
},
// 表單修改
beforeRouteLeave (to, from, next){
console.log('beforeRouteLeave 組件中的路由')
next()
},
props:['name'],
template:'#sapp',
};
const test = {
beforeRouteEnter(to, from, next){
console.log('test -- beforeRouteEnter 組件中的路由');
//next();
next(vm=>{
console.log(vm)
})
},
beforeRouteUpdate(to, from, next){
console.log('test -- beforeRouteUpdate 組件中的路由')
next()
},
beforeRouteLeave (to, from, next){
console.log('test -- beforeRouteLeave 組件中的路由')
next()
},
template:'<h1>123</h1>'}
const routes=[
{
path:"/app/:id",
component:sapp,
beforeEnter(to, from, next){
console.log('beforeEnter 路由中的路由');
next();
}
},
{
path:'/test',
component:test,
beforeEnter(to, from, next){
console.log('test -- beforeEnter 路由中的路由');
next();
}
},
];
const router = new VueRouter({
routes // (縮寫) 相當于 routes: routes
});
// 驗證用戶登錄
router.beforeEach((to, from, next)=>{
console.log('beforeEach 生命周期');
//next('/login') 接受的參數和router-link一致
next();
});
router.beforeResolve((to, from, next)=>{
console.log('beforeResolve 生命周期');
next()
});
// 跳轉之后執行 沒有next
router.afterEach((to, from)=>{
console.log('afterEach 生命周期');
});
var vms = new Vue({
el: "#app",
router,
})
</script>
</body>
</html>
~~~
>[info] ## 官方的守衛導航周期總結
~~~
1.導航被觸發。
2.在失活的組件里調用離開守衛。
3.調用全局的 beforeEach 守衛。
4.在重用的組件里調用 beforeRouteUpdate 守衛 (2.2+)。
5.在路由配置里調用 beforeEnter。
6.解析異步路由組件。
7.在被激活的組件里調用 beforeRouteEnter。
8.調用全局的 beforeResolve 守衛 (2.5+)。
9.導航被確認。
10.調用全局的 afterEach 鉤子。
11.觸發 DOM 更新。
12.用創建好的實例調用 beforeRouteEnter 守衛中傳給 next 的回調函數。
~~~
- Vue--基礎篇章
- Vue -- 介紹
- Vue -- MVVM
- Vue -- 創建Vue實例
- Vue -- 模板語法
- Vue -- 指令用法
- v-cloak -- 遮蓋
- v-bind -- 標簽屬性動態綁定
- v-on -- 綁定事件
- v-model -- 雙向數據綁定
- v-for -- 只是循環沒那么簡單
- 小知識點 -- 計劃內屬性
- key -- 屬性為什么要加
- 案例說明
- v-if/v-show -- 顯示隱藏
- v-for 和 v-if 同時使用
- v-pre -- 不渲染大大胡語法
- v-once -- 只渲染一次
- Vue -- class和style綁定
- Vue -- filter 過濾器
- Vue--watch/computed/fun
- watch -- 巧妙利用watch思想
- Vue -- 自定義指令
- Vue -- $方法
- Vue--生命周期
- Vue -- 專屬ajax
- Vue -- transition過渡動畫
- 前面章節的案例
- 案例 -- 跑馬燈效果
- 案例 -- 選項卡內容切換
- 案例-- 篩選商品
- 案例 -- 搜索/刪除/更改
- 案例 -- 用computed做多選
- 案例 -- checked 多選
- Vue--組件篇章
- component -- 介紹
- component -- 使用全局組件
- component -- 使用局部組件
- component -- 組件深入
- component -- 組件傳值父傳子
- component -- 組件傳值子傳父
- component -- 子傳父語法糖拆解
- component -- 父組件操作子組件
- component -- is 動態切換組件
- component -- 用v-if/v-show控制子組件
- component -- 組件切換的動畫效果
- component -- slot 插槽
- component -- 插槽2.6
- component -- 組件的生命周期
- component -- 基礎組件全局注冊
- VueRouter--獲取路由參數
- VueRouter -- 介紹路由
- VueRouter -- 安裝
- VueRouter -- 使用
- VueRouter--router-link簡單參數
- VueRouter--router-link樣式問題
- VueRouter--router-view動畫效果
- VueRouter -- 匹配優先級
- vueRouter -- 動態路由
- VueRouter -- 命名路由
- VueRouter -- 命名視圖
- VueRouter--$router 獲取函數
- VueRouter--$route獲取參數
- VueRouter--路由嵌套
- VueRouter -- 導航守衛
- VueRouter -- 寫在最后
- Vue--模塊化方式結構
- webpack--自定義配置
- webpack -- 自定義Vue操作
- VueCli -- 3.0可視化配置
- VueCli -- 3.0 項目目錄
- Vue -- 組件升級篇
- Vue -- 組件種類與組件組成
- Vue -- 組件prop、event、slot 技巧
- Vue -- 組件通信(一)
- Vue -- 組件通信(二)
- Vue -- 組件通信(三)
- Vue -- 組件通信(四)
- Vue -- 組件通信(五)
- Vue -- 組件通信(六)
- Vue -- bus非父子組件通信
- Vue -- 封裝js插件成vue組件
- vue組件分裝 -- 進階篇
- Vue -- 組件封裝splitpane(分割面板)
- UI -- 正式封裝
- Vue -- iview 可編輯表格案例
- Ui -- iview 可以同時編輯多行
- Vue -- 了解遞歸組件
- UI -- 正式使用遞歸菜單
- Vue -- iview Tree組件
- Vue -- 利用通信仿寫一個form驗證
- Vue -- 使用自己的Form
- Vue -- Checkbox 組件
- Vue -- CheckboxGroup.vue
- Vue -- Alert 組件
- Vue -- 手動掛載組件
- Vue -- Alert開始封裝
- Vue -- 動態表單組件
- Vue -- Vuex組件的狀態管理
- Vuex -- 參數使用理解
- Vuex -- state擴展
- Vuex -- getters擴展
- Vuex--mutations擴展
- Vuex -- Action 異步
- Vuex -- plugins插件
- Vuex -- v-model寫法
- Vuex -- 更多
- VueCli -- 技巧總結篇
- CLI -- 路由基礎
- CLI -- 路由升級篇
- CLI --異步axios
- axios -- 封裝axios
- CLI -- 登錄寫法
- CLI -- 權限
- CLI -- 簡單權限
- CLI -- 動態路由加載
- CLI -- 數據性能優化
- ES6 -- 類的概念
- ES6類 -- 基礎
- ES6 -- 繼承
- ES6 -- 工作實戰用類數據管理
- JS -- 適配器模式
- ES7 -- 裝飾器(Decorator)
- 裝飾器 -- 裝飾器修飾類
- 裝飾器--修飾類方法(知識擴展)
- 裝飾器 -- 裝飾器修飾類中的方法
- 裝飾器 -- 執行順序
- Reflect -- es6 自帶版本
- Reflect -- reflect-metadata 版本
- 實戰 -- 驗證篇章(基礎)
- 驗證篇章 -- 搭建和目錄
- 驗證篇章 -- 創建基本模板
- 驗證篇章 -- 使用
- 實戰 -- 更新模型(為了迎合ui升級)
- 實戰 -- 模型與接口對接
- TypeSprict -- 基礎篇章
- TS-- 搭建(一)webpack版本
- TS -- 搭建(二)直接使用
- TS -- 基礎類型
- TS -- 枚舉類型
- TS -- Symbol
- TS -- interface 接口
- TS -- 函數
- TS -- 泛型
- TS -- 類
- TS -- 類型推論和兼容
- TS -- 高級類型(一)
- TS -- 高級類型(二)
- TS -- 關于模塊解析
- TS -- 聲明合并
- TS -- 混入
- Vue -- TS項目模擬
- TS -- vue和以前代碼對比
- TS -- vue簡單案例上手
- Vue -- 簡單弄懂VueRouter過程
- VueRouter -- 實現簡單Router
- Vue-- 原理2.x源碼簡單理解
- 了解 -- 簡單的響應式工作原理
- 準備工作 -- 了解發布訂閱和觀察者模式
- 了解 -- 響應式工作原理(一)
- 了解 -- 響應式工作原理(二)
- 手寫 -- 簡單的vue數據響應(一)
- 手寫 -- 簡單的vue數據響應(二)
- 模板引擎可以做的
- 了解 -- 虛擬DOM
- 虛擬dom -- 使用Snabbdom
- 閱讀 -- Snabbdom
- 分析snabbdom源碼 -- h函數
- 分析snabbdom -- init 方法
- init 方法 -- patch方法分析(一)
- init 方法 -- patch方法分析(二)
- init方法 -- patch方法分析(三)
- 手寫 -- 簡單的虛擬dom渲染
- 函數表達解析 - h 和 create-element
- dom操作 -- patch.js
- Vue -- 完成一個minVue
- minVue -- 打包入口
- Vue -- new實例做了什么
- Vue -- $mount 模板編譯階段
- 模板編譯 -- 分析入口
- 模板編譯 -- 分析模板轉譯
- Vue -- mountComponent 掛載階段
- 掛載階段 -- vm._render()
- 掛載階段 -- vnode
- 備份章節
- Vue -- Nuxt.js
- Vue3 -- 學習
- Vue3.x --基本功能快速預覽
- Vue3.x -- createApp
- Vue3.x -- 生命周期
- Vue3.x -- 組件
- vue3.x -- 異步組件???
- vue3.x -- Teleport???
- vue3.x -- 動畫章節 ??
- vue3.x -- 自定義指令 ???
- 深入響應性原理 ???
- vue3.x -- Option API VS Composition API
- Vue3.x -- 使用set up
- Vue3.x -- 響應性API
- 其他 Api 使用
- 計算屬性和監聽屬性
- 生命周期
- 小的案例(一)
- 小的案例(二)-- 泛型
- Vue2.x => Vue3.x 導讀
- v-for 中的 Ref 數組 -- 非兼容
- 異步組件
- attribute 強制行為 -- 非兼容
- $attrs 包括 class & style -- 非兼容
- $children -- 移除
- 自定義指令 -- 非兼容
- 自定義元素交互 -- 非兼容
- Data選項 -- 非兼容
- emits Option -- 新增
- 事件 API -- 非兼容
- 過濾器 -- 移除
- 片段 -- 新增
- 函數式組件 -- 非兼容
- 全局 API -- 非兼容
- 全局 API Treeshaking -- 非兼容
- 內聯模板 Attribute -- 非兼容
- key attribute -- 非兼容
- 按鍵修飾符 -- 非兼容
- 移除 $listeners 和 v-on.native -- 非兼容
- 在 prop 的默認函數中訪問 this -- ??
- 組件使用 v-model -- 非兼容
- 渲染函數 API -- ??
- Slot 統一 ??
- 過渡的 class 名更改 ???
- Transition Group 根元素 -- ??
- v-if 與 v-for 的優先級對比 -- 非兼容
- v-bind 合并行為 非兼容
- 監聽數組 -- 非兼容