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