路由vue-router进阶
目錄
- 1. 導航守衛(wèi)
- 1.1. 全局守衛(wèi)
- 1.2. 全局解析守衛(wèi)
- 1.3. 全局后置鉤子
- 1.4. 路由獨享的守衛(wèi)
- 1.5. 組件內的守衛(wèi)
- 1.6. 完整的導航解析流程
- 2. 路由元信息
- 3. 獲取數據
- 3.1. 導航完成后獲取數據
- 3.2. 在導航完成前獲取數據
1. 導航守衛(wèi)
正如其名,vue-router 提供的導航守衛(wèi)主要用來通過跳轉或取消的方式守衛(wèi)導航。
有多種機會植入路由導航過程中:全局的, 單個路由獨享的, 或者組件級的。
記住參數或查詢的改變并不會觸發(fā)進入/離開的導航守衛(wèi)
1.1. 全局守衛(wèi)
你可以使用 router.beforeEach 注冊一個全局前置守衛(wèi):
const router = new VueRouter({ ... })router.beforeEach((to, from, next) => {// ...
}) 當一個導航觸發(fā)時,全局前置守衛(wèi)按照創(chuàng)建順序調用。守衛(wèi)是異步解析執(zhí)行,此時導航在所有守衛(wèi) resolve 完之前一直處于 等待中。
每個守衛(wèi)方法接收三個參數:
to: Route: 即將要進入的目標 路由對象
from: Route: 當前導航正要離開的路由
next: Function: 一定要調用該方法來 resolve 這個鉤子。執(zhí)行效果依賴 next 方法的調用參數。
next(): 進行管道中的下一個鉤子。如果全部鉤子執(zhí)行完了,則導航的狀態(tài)就是 confirmed (確認的)。
next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了(可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到 from 路由對應的地址。
next('/') 或者 next({ path: '/' }): 跳轉到一個不同的地址。當前的導航被中斷,然后進行一個新的導航。
next(error): (2.4.0+) 如果傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 注冊過的回調。
確保要調用 next 方法,否則鉤子就不會被 resolved。
1.2. 全局解析守衛(wèi)
2.5.0 新增
在 2.5.0+ 你可以用 router.beforeResolve 注冊一個全局守衛(wèi)。這和 router.beforeEach 類似,區(qū)別是在導航被確認之前,同時在所有組件內守衛(wèi)和異步路由組件被解析之后,解析守衛(wèi)就被調用。
1.3. 全局后置鉤子
你也可以注冊全局后置鉤子,然而和守衛(wèi)不同的是,這些鉤子不會接受 next 函數也不會改變導航本身:
router.afterEach((to, from) => {// ...
}) 1.4. 路由獨享的守衛(wèi)
你可以在路由配置上直接定義 beforeEnter 守衛(wèi):
const router = new VueRouter({routes: [{path: '/foo',component: Foo,beforeEnter: (to, from, next) => {// ...}}]
}) 這些守衛(wèi)與全局前置守衛(wèi)的方法參數是一樣的。
1.5. 組件內的守衛(wèi)
最后,你可以在路由組件內直接定義以下路由導航守衛(wèi):
- beforeRouteEnter
- beforeRouteUpdate (2.2 新增)
- beforeRouteLeave
const Foo = {template: `...`,beforeRouteEnter (to, from, next) {// 在渲染該組件的對應路由被 confirm 前調用// 不!能!獲取組件實例 `this`// 因為當守衛(wèi)執(zhí)行前,組件實例還沒被創(chuàng)建},beforeRouteUpdate (to, from, next) {// 在當前路由改變,但是該組件被復用時調用// 舉例來說,對于一個帶有動態(tài)參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,// 由于會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。// 可以訪問組件實例 `this`},beforeRouteLeave (to, from, next) {// 導航離開該組件的對應路由時調用// 可以訪問組件實例 `this`}
} beforeRouteEnter 守衛(wèi) 不能 訪問 this,因為守衛(wèi)在導航確認前被調用,因此即將登場的新組件還沒被創(chuàng)建。
不過,你可以通過傳一個回調給 next來訪問組件實例。在導航被確認的時候執(zhí)行回調,并且把組件實例作為回調方法的參數。
beforeRouteEnter (to, from, next) {next(vm => {// 通過 `vm` 訪問組件實例})
} 你可以 在 beforeRouteLeave 中直接訪問 this。這個離開守衛(wèi)通常用來禁止用戶在還未保存修改前突然離開。可以通過 next(false) 來取消導航。
1.6. 完整的導航解析流程
- 導航被觸發(fā)。
- 在失活的組件里調用離開守衛(wèi)。
- 調用全局的 beforeEach 守衛(wèi)。
- 在重用的組件里調用 beforeRouteUpdate 守衛(wèi) (2.2+)。
- 在路由配置里調用 beforeEnter。
- 解析異步路由組件。
- 在被激活的組件里調用 beforeRouteEnter。
- 調用全局的 beforeResolve 守衛(wèi) (2.5+)。
- 導航被確認。
- 調用全局的 afterEach 鉤子。
- 觸發(fā) DOM 更新。
- 用創(chuàng)建好的實例調用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調函數。
2. 路由元信息
定義路由的時候可以配置 meta 字段:
const router = new VueRouter({routes: [{path: '/foo',component: Foo,children: [{path: 'bar',component: Bar,// a meta fieldmeta: { requiresAuth: true }}]}]
}) 那么如何訪問這個 meta 字段呢?
首先,我們稱呼 routes 配置中的每個路由對象為 路由記錄。路由記錄可以是嵌套的,因此,當一個路由匹配成功后,他可能匹配多個路由記錄
例如,根據上面的路由配置,/foo/bar 這個 URL 將會匹配父路由記錄以及子路由記錄。
一個路由匹配到的所有路由記錄會暴露為 $route 對象(還有在導航守衛(wèi)中的路有對象)的 $route.matched 數組。因此,我們需要遍歷 $route.matched 來檢查路由記錄中的 meta 字段。
下面例子展示在全局導航守衛(wèi)中檢查元字段:
router.beforeEach((to, from, next) => {if (to.matched.some(record => record.meta.requiresAuth)) {// this route requires auth, check if logged in// if not, redirect to login page.if (!auth.loggedIn()) {next({path: '/login',query: { redirect: to.fullPath }})} else {next()}} else {next() // 確保一定要調用 next()}
}) 3. 獲取數據
有時候,進入某個路由后,需要從服務器獲取數據。例如,在渲染用戶信息時,你需要從服務器獲取用戶的數據。我們可以通過兩種方式來實現:
導航完成之后獲取:先完成導航,然后在接下來的組件生命周期鉤子中獲取數據。在數據獲取期間顯示『加載中』之類的指示。
導航完成之前獲取:導航完成前,在路由進入的守衛(wèi)中獲取數據,在數據獲取成功后執(zhí)行導航。
從技術角度講,兩種方式都不錯 —— 就看你想要的用戶體驗是哪種。
3.1. 導航完成后獲取數據
當你使用這種方式時,我們會馬上導航和渲染組件,然后在組件的 created 鉤子中獲取數據。這讓我們有機會在數據獲取期間展示一個 loading 狀態(tài),還可以在不同視圖間展示不同的 loading 狀態(tài)。
假設我們有一個 Post 組件,需要基于 $route.params.id 獲取文章數據:
<template><div class="post"><div class="loading" v-if="loading">Loading...</div><div v-if="error" class="error">{{ error }}</div><div v-if="post" class="content"><h2>{{ post.title }}</h2><p>{{ post.body }}</p></div></div>
</template>
export default {data () {return {loading: false,post: null,error: null}},created () {// 組件創(chuàng)建完后獲取數據,// 此時 data 已經被 observed 了this.fetchData()},watch: {// 如果路由有變化,會再次執(zhí)行該方法'$route': 'fetchData'},methods: {fetchData () {this.error = this.post = nullthis.loading = true// replace getPost with your data fetching util / API wrappergetPost(this.$route.params.id, (err, post) => {this.loading = falseif (err) {this.error = err.toString()} else {this.post = post}})}}
} 3.2. 在導航完成前獲取數據
通過這種方式,我們在導航轉入新的路由前獲取數據。我們可以在接下來的組件的 beforeRouteEnter 守衛(wèi)中獲取數據,當數據獲取成功后只調用 next 方法。
export default {data () {return {post: null,error: null}},beforeRouteEnter (to, from, next) {getPost(to.params.id, (err, post) => {next(vm => vm.setData(err, post))})},// 路由改變前,組件就已經渲染完了// 邏輯稍稍不同beforeRouteUpdate (to, from, next) {this.post = nullgetPost(to.params.id, (err, post) => {this.setData(err, post)next()})},methods: {setData (err, post) {if (err) {this.error = err.toString()} else {this.post = post}}}
} 在為后面的視圖獲取數據時,用戶會停留在當前的界面,因此建議在數據獲取期間,顯示一些進度條或者別的指示。如果數據獲取失敗,同樣有必要展示一些全局的錯誤提醒。
轉載于:https://www.cnblogs.com/redirect/p/8436028.html
總結
以上是生活随笔為你收集整理的路由vue-router进阶的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 沈腾公交强吻女主是什么电视或者电影
- 下一篇: 驾校b2多少钱啊?