日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

vue-router进阶:路由使用归纳、路由导航守卫、导航守卫解析流程、

發布時間:2025/3/12 vue 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue-router进阶:路由使用归纳、路由导航守卫、导航守卫解析流程、 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、定義和理解

導航守衛的作用vue-router?提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。

》》項目中應用場景舉例:路由頁面跳轉時候進行登陸驗證;路由跳轉判斷;

?

有多種機會植入路由導航過程中全局路由, 單個路由獨享的, 或者組件級的

全局守衛包括:router.beforeEach(是全局前置守衛)、router.beforeResolve(是全局解析守衛)、router.afterEach(是全局后置鉤子)

單個路由獨享的導航守衛:在路由配置上直接定義 beforeEnter?守衛

組件內守衛包括:在組件內定義路由的導航守衛,有beforeRouteEnter 、beforeRouteUpdate 、beforeRouteLeave

?

每個導航守衛都接受3個參數 from 、to、next() ,參數的定義如下:

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() 注冊過的回調。

?

注意事項:

1、確保要調用?next?方法,否則鉤子就不會被 resolved。

2、當一個導航觸發時,導航守衛按照順序調用。守衛是異步解析執行,導航在所有守衛 resolve 完之前一直處于 等待中

?

?

二、導航守衛使用

?

首先vue-router知識回顧:

0、在vue項目中使用vue-router步驟概述:

// 0. 如果使用模塊化機制編程,導入Vue和VueRouter,要調用 Vue.use(VueRouter)// 1. 定義 (路由) 組件。 // 可以從其他文件 import 進來 const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' }// 2. 定義路由 // 每個路由應該映射一個組件。 其中"component" 可以是 // 通過 Vue.extend() 創建的組件構造器, // 或者,只是一個組件配置對象。 // 我們暫時不套路討論嵌套路由、傳參、元數據、導航守衛等。 const routes = [{ path: '/foo', component: Foo },{ path: '/bar', component: Bar } ]// 3. 創建 router 實例,然后傳 `routes` 配置 // 你還可以傳別的配置參數, 不過先這么簡單著吧。 const router = new VueRouter({routes // (縮寫) 相當于 routes: routes })// 4. 創建和掛載根實例。 // 記得要通過 router 配置參數注入路由, // 從而讓整個應用都有路由功能 const app = new Vue({router }).$mount('#app')// 現在,應用已經啟動了!

?

1、可以在任何組件內通過?this.$router?訪問路由器,也可以通過?this.$route?訪問當前路由:

// Home.vue export default {computed: {username () {// 我們很快就會看到 `params` 是什么return this.$route.params.username}},methods: {goBack () {window.history.length > 1? this.$router.go(-1): this.$router.push('/')}} }

?

2、動態路由匹配時使用this.$route.params獲取路由的路徑參數

應用場景:需要把某種模式匹配到的所有路由,全都映射到同個組件。例如,我們有一個?User?組件,對于所有 ID 各不相同的用戶,都要使用這個組件來渲染。又像?/user/foo?和?/user/bar?都將映射到相同的路由。

?

注意:可以在一個路由中設置多段“路徑參數”,如下:

模式匹配路徑$route.params
/user/:username/user/evan{ username: 'evan' }
/user/:username/post/:post_id/user/evan/post/123{ username: 'evan', post_id: '123' }

當使用路由參數時,例如從?/user/foo?導航到?/user/bar,原來的組件實例會被復用。因為兩個路由都渲染同個組件,比起銷毀再創建,復用則顯得更加高效。不過,這也意味著組件的生命周期鉤子不會再被調用

參數或查詢的改變并不會觸發進入/離開的導航守衛。可以通過觀察?$route?對象來應對這些變化,或使用??beforeRouteUpdate?的組件內守衛。

?

3、復用組件時,想對路由參數的變化作出響應的話,你可以簡單地 watch (監測變化)?$route?對象:

const User = {template: '...',watch: {'$route' (to, from) {// 對路由變化作出響應...}} }

或者使用 2.2 中引入的?beforeRouteUpdate?導航守衛:

const User = {template: '...',beforeRouteUpdate (to, from, next) {// react to route changes...// don't forget to call next()} }

?

4、在router配置文件中使用通配符 (*)捕獲所有路由或 404 Not found 路由

注意:通常含有通配符的路由應該放在最后。路由?{ path: '*' }?通常用于客戶端 404 錯誤。如果你使用了History 模式,請確保正確配置你的服務器。

同一個路徑可以匹配多個路由,此時,匹配的優先級就按照路由的定義順序:誰先定義的,誰的優先級就最高

當使用一個通配符時,$route.params?內會自動添加一個名為?pathMatch?參數。它包含了 URL 通過通配符被匹配的部分:

// 給出一個路由 { path: '/user-*' } this.$router.push('/user-admin') this.$route.params.pathMatch // 'admin' // 給出一個路由 { path: '*' } this.$router.push('/non-existing') this.$route.params.pathMatch // '/non-existing'

?

5、使用vue-router嵌套路由時,在路由定義文件中使用children?配置:

注意事項:以?/?開頭的嵌套路徑會被當作根路徑。 這讓你充分的使用嵌套組件而無須設置嵌套的路徑。

const router = new VueRouter({routes: [{ path: '/user/:id', component: User,children: [{// 當 /user/:id/profile 匹配成功,// UserProfile 會被渲染在 User 的 <router-view> 中path: 'profile',component: UserProfile},{// 當 /user/:id/posts 匹配成功// UserPosts 會被渲染在 User 的 <router-view> 中path: 'posts',component: UserPosts}]}] })

?

6、vue-router路由導航可以在組件中使用<router-link :to="...">?的形式外,還有JS編程式的導航(包括可以調用?this.$router.push(location, onComplete?, onAbort?) 和?router.replace(location, onComplete?, onAbort?),以及router.go(n)?)

注意事項:

  • 如果提供了?path,params?會被忽略;
  • 如果目的地和當前路由相同,只有參數發生了改變 (比如從一個用戶資料到另一個?/users/1?->?/users/2),你需要使用?beforeRouteUpdate?來響應這個變化 (比如抓取用戶信息);
  • router.push?方法。這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器后退按鈕時,則回到之前的 URL。router.replace?方法它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄。
  • 在 2.2.0+,可選的在?router.push?或?router.replace?中提供?onComplete?和?onAbort?回調作為第二個和第三個參數。這些回調將會在導航成功完成 (在所有的異步鉤子被解析之后) 或終止 (導航到相同的路由、或在當前導航完成之前導航到另一個不同的路由) 的時候進行相應的調用。
const userId = '123' router.push({ name: 'user', params: { userId }}) // -> /user/123 router.push({ path: `/user/${userId}` }) // -> /user/123 // 這里的 params 不生效 router.push({ path: '/user', params: { userId }}) // -> /user// 在瀏覽器記錄中前進一步,等同于 history.forward() router.go(1)// 后退一步記錄,等同于 history.back() router.go(-1)

router.push、?router.replace?和?router.go?跟?window.history.pushState、?window.history.replaceState?和?window.history.go好像, 實際上它們確實是效仿?window.historyAPI 的。

?

7、當需要在一個組件頁面展示多個路由視圖 router-view ,需要給視圖命名:

<router-view class="view one"></router-view> <router-view class="view two" name="a"></router-view> <router-view class="view three" name="b"></router-view> const router = new VueRouter({routes: [{path: '/',components: {default: Foo,a: Bar,b: Baz}}] })

注意:正確使用?components配置 (帶上 s):

?

8、vue-router路由重定向和別名使用

“重定向”的意思是,當用戶訪問?/a時,URL 將會被替換成?/b,然后匹配路由為?/b;重定向不能指向自身,會形成死循環。

“別名”的意思是給路由取“小名”,/a?的別名是?/b,意味著,當用戶訪問?/b?時,URL 會保持為?/b,但是路由匹配則為?/a,就像用戶訪問?/a?一樣。

const router = new VueRouter({routes: [{ path: '/a', redirect: '/b' },{ path: '/b', redirect: { name: 'foo' }},{ path: '/c', redirect: to => {// 方法接收 目標路由 作為參數// return 重定向的 字符串路徑/路徑對象}},{ path: '/a', component: A, alias: '/b' }] })

?

9、vue-router使用路由進行組件傳參時,通過props取代 $route.params 可以降低耦合度:

注意:在組件中使用?$route?會使之與其對應路由形成高度耦合,從而使組件只能在某些特定的 URL 上使用,限制了其靈活性。通過props取代,這樣你便可以在任何地方使用該組件,使得該組件更易于重用和測試。

如果?props?被設置為?true,route.params?將會被設置為組件屬性。

const User = { //$route 的耦合template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({routes: [{ path: '/user/:id', component: User }] })const User = { //通過 props 解耦props: ['id'],template: '<div>User {{ id }}</div>' } const router = new VueRouter({routes: [{ path: '/user/:id', component: User, props: true },// 對于包含命名視圖的路由,你必須分別為每個命名視圖添加 `props` 選項:{path: '/user/:id',components: { default: User, sidebar: Sidebar },props: { default: true, sidebar: false }}] })

如果?props?是一個對象,它會被按原樣設置為組件屬性。當?props?是靜態的時候有用。

const router = new VueRouter({routes: [{ path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }] })

?

你可以創建一個函數返回?props。這樣你便可以將參數轉換成另一種類型,將靜態值與基于路由的值結合等等。

const router = new VueRouter({routes: [{ path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }] })

?

?

開始導航守衛使用demo:

注意事項:注意導航守衛并沒有應用在跳轉路由上,而僅僅應用在其目標上。

1、全局前置守衛 router.beforeEach

const router = new VueRouter({ ... })router.beforeEach((to, from, next) => {// ... })

?

2、全局解析守衛?router.beforeResolve

在導航被確認之前,同時在所有組件內守衛和異步路由組件被解析之后,解析守衛就被調用。

?

?

3、全局后置鉤子router.afterEach

和守衛不同的是,這些鉤子不會接受?next?函數也不會改變導航本身:

router.afterEach((to, from) => {// ... })

?

4、路由獨享的守衛router.beforeEnter

是在路由配置上直接定義?beforeEnter?守衛:

const router = new VueRouter({routes: [{path: '/foo',component: Foo,beforeEnter: (to, from, next) => {// ...}}] })

?

5、組件內的守衛?beforeRouteEnter、beforeRouteUpdate?(2.2 新增)、beforeRouteLeave

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?守衛?不能?訪問?this的解決方式是:通過傳一個回調給?next來訪問組件實例。在導航被確認的時候執行回調,并且把組件實例作為回調方法的參數。

注意:beforeRouteEnter?是支持給?next?傳遞回調的唯一守衛。對于?beforeRouteUpdate?和?beforeRouteLeave?來說,this?已經可用了,所以不支持傳遞回調,因為沒有必要了。

beforeRouteEnter (to, from, next) {next(vm => {// 通過 `vm` 訪問組件實例}) }

?

這個離開守衛通常用來禁止用戶在還未保存修改前突然離開。該導航可以通過?next(false)?來取消。

beforeRouteLeave (to, from , next) {const answer = window.confirm('Do you really want to leave? you have unsaved changes!')if (answer) {next()} else {next(false)} }

?

?

三、導航守衛解析流程:

  • 導航被觸發。
  • 在失活的組件里調用離開守衛。
  • 調用全局的?beforeEach?守衛。
  • 在重用的組件里調用?beforeRouteUpdate?守衛 (2.2+)。
  • 在路由配置里調用?beforeEnter。
  • 解析異步路由組件。
  • 在被激活的組件里調用?beforeRouteEnter。
  • 調用全局的?beforeResolve?守衛 (2.5+)。
  • 導航被確認。
  • 調用全局的?afterEach?鉤子。
  • 觸發 DOM 更新。
  • 用創建好的實例調用?beforeRouteEnter?守衛中傳給?next?的回調函數。
  • ?

    ?

    ?

    四、其他:路由元信息、過渡動效、數據獲取、滾動位置、懶加載

    ?

    路由元信息:

    定義路由的時候可以設置meta字段,可以存儲該路由相關信息(例如:設置每個路由的title,取路由的title設置為選項卡的標題);還可以用來設置頁面權限要求

    {path: '/router2',name: 'router2',component:router2,meta:{title:"router2"}} // 全局前置守衛 router.beforeEach((to,from,next) => {console.log(to);console.log(from);if(to.meta.title) {document.title = to.meta.title;} else {document.title = '我是默認的title'}next(); });

    ?

    ?

    路由過渡動效:

    Vue 在插入、更新或者移除 DOM 時,提供多種不同方式的應用過渡效果。

    const Foo = {template: `<transition name="slide"><div class="foo">...</div></transition>` }const Bar = {template: `<transition name="fade"><div class="bar">...</div></transition>` }<!-- 使用動態的 transition name --> <transition :name="transitionName"><router-view></router-view> </transition>// 接著在父組件內 // watch $route 決定使用哪種過渡 watch: {'$route' (to, from) {const toDepth = to.path.split('/').lengthconst fromDepth = from.path.split('/').lengththis.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'} }

    ?

    ?

    路由數據獲取:(分別有導航完成前和完成后獲取)

    有時候,進入某個路由后,需要從服務器獲取數據。例如,在渲染用戶信息時,你需要從服務器獲取用戶的數據。我們可以通過兩種方式來實現:

    • 導航完成之后獲取:先完成導航,然后在接下來的組件生命周期鉤子中獲取數據。在數據獲取期間顯示“加載中”之類的指示。
    • 導航完成之前獲取:導航完成前,在路由進入的守衛中獲取數據,在數據獲取成功后執行導航。從技術角度講,兩種方式都不錯 —— 就看你想要的用戶體驗是哪種。

    導航完成后獲取數據,我們會馬上導航和渲染組件,然后在組件的?created?鉤子中獲取數據。

    export default {data () {return {loading: false,post: null,error: null}},created () {// 組件創建完后獲取數據,// 此時 data 已經被 observed 了this.fetchData()},watch: {// 如果路由有變化,會再次執行該方法'$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}})}} }

    我們在導航轉入新的路由前獲取數據。我們可以在接下來的組件的?beforeRouteEnter?守衛中獲取數據,當數據獲取成功后只調用?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}}} }

    ?

    路由滾動行為:

    使用前端路由,當切換到新路由時,想要頁面滾到頂部,或者是保持原先的滾動位置,就像重新加載頁面那樣。?vue-router?能做到,而且更好,它讓你可以自定義路由切換時頁面如何滾動。

    注意: 這個功能只在支持?history.pushState?的瀏覽器中可用。

    當創建一個 Router 實例,你可以提供一個?scrollBehavior?方法:

    const router = new VueRouter({routes: [...],scrollBehavior (to, from, savedPosition) {// return 期望滾動到哪個的位置} })

    scrollBehavior?方法接收?to?和?from?路由對象。第三個參數?savedPosition?當且僅當?popstate導航 (通過瀏覽器的 前進/后退 按鈕觸發) 時才可用。

    這個方法返回滾動位置的對象信息,長這樣:

    • { x: number, y: number }
    • { selector: string, offset? : { x: number, y: number }}?(offset 只在 2.6.0+ 支持)

    如果返回一個 falsy (譯者注:falsy 不是?false,參考這里)的值,或者是一個空對象,那么不會發生滾動。

    舉例:

    scrollBehavior (to, from, savedPosition) {return { x: 0, y: 0 } }

    對于所有路由導航,簡單地讓頁面滾動到頂部。

    返回?savedPosition,在按下 后退/前進 按鈕時,就會像瀏覽器的原生表現那樣:

    scrollBehavior (to, from, savedPosition) {if (savedPosition) {return savedPosition} else {return { x: 0, y: 0 }} }

    如果你要模擬“滾動到錨點”的行為:

    scrollBehavior (to, from, savedPosition) {if (to.hash) {return {selector: to.hash}} }

    ?

    ?

    路由懶加載:

    當打包構建應用時,JavaScript 包會變得非常大,影響頁面加載。如果我們能把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應組件,這樣就更加高效了。

    結合 Vue 的異步組件和 Webpack 的代碼分割功能,輕松實現路由組件的懶加載。

    一個能夠被 Webpack 自動代碼分割的異步組件。

    const Foo = () => import('./Foo.vue')

    在路由配置中什么都不需要改變,只需要像往常一樣使用?Foo:

    const router = new VueRouter({routes: [{ path: '/foo', component: Foo }] })

    ?

    ?

    ?

    五、應用demo

    vue路由登陸驗證:

    前言:vue的項目的登錄狀態如果用vuex狀態管理,頁面一刷新vuex管理的狀態就會消失,所以,會將登錄的狀態寫到web Storage中進行存儲管理。

    步驟:

    1、router/index.js 》在需要登錄驗證的路由元信息里加入登錄驗證標識requiresAuth:true

    routers: [{ path: '/home',name: 'home',component: Home,meta: { requiresAuth: true }},{path: '/login',name: 'Login',component: Login},]

    2、登陸組件從服務端獲取到token,將登錄狀態寫入web Storage里

    login() {this.$api.login().then(function(res) {//調用axios二次封裝的login方法,關閉mockjs時會傳遞到nodejssessionStorage.setItem('accessToken', res.data.token) // 成果返回后放置token到Cookie //console.log("登陸響應",JSON.stringify(res.data));router.push('/home') // 登錄成功,跳轉到主頁}).catch(function(res) {alert(res);});},

    ?

    3、router/index.js 》再路由配置文件中使用全局前置導航守衛

    //全局前置導航守衛,導航跳轉前進行token登陸令牌判斷 router.beforeEach((to, from, next) => {if(to.path === '/login') { next() }else {if(to.meta.requiresAuth && !sessionStorage.getItem('accessToken')) {next({ path: '/login' })}else { //如果不需要登錄驗證,或者已經登錄成功,則直接放行next() } }});

    ?

    ?

    官網API:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

    ?

    總結

    以上是生活随笔為你收集整理的vue-router进阶:路由使用归纳、路由导航守卫、导航守卫解析流程、的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。