超詳細!Vue-Router手把手教程

鵬多多發表於2021-08-09

最近在重溫vue全家桶,再看一遍感覺記憶更深刻,所以專門記錄一下(本文vue-router版本為v3.x)。

1,router-view

<router-view>是一個功能性元件,用於渲染路徑匹配到的檢視元件。可以配合<transition><keep-alive>使用。如果兩個一起用,要確保在內層使用<keep-alive>

<router-view></router-view>
<!--或-->
<router-view name="footer"></router-view>

如果 <router-view>設定了名稱,則會渲染對應的路由配置中 components下的相應元件。

2,router-link

<router-link>標籤支援使用者在具有路由功能的應用中(點選)導航。

屬性 型別 說明
to String/Object 目標路由/目標位置的物件
replace Boolean 不留下導航記錄
append Boolean 在當前路徑後加路徑 /a => /a/b
tag String 指定渲染成何種標籤
active-class String 啟用時使用的Class
<router-link :to="{ path: '/login'}" replace tag="span"></router-link>

3,重定向redirect

根路由重定向到login

const router = new VueRouter({
  routes: [
    { path: '/', redirect: '/login' }
  ]
})

動態返回重定向目標

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // 方法接收 目標路由 作為引數
      // return 重定向的 字串路徑/路徑物件
    }}
  ]
})

4,路由別名

路由訪問/b時,URL會保持為/b,但是路由匹配則為/a

const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

5,路由傳參props

使用props,避免和$route過度耦合,這樣就可以直接在元件中使用props接收引數

5.1,布林模式

在路由後面寫上引數,並設定propstrue

{
	path: '/vuex/:id',
	name: 'Vuex',
	component: () => import('@/view/vuex'),
	props: true,
	mate: {
		title: 'vuex'
	}
}

設定跳轉需要傳遞的引數params

<router-link :to="{name:'Vuex', params: {id: '99999'}}" tag="h1">跳轉</router-link>
<!--或者-->
toNext() {
    this.$router.push({
    	name: 'Vuex',
    	params: {
    		id: '99999'
    	}
    })
}

在跳轉過去的頁面,通過props或者this.$params取參

props: {
	id: {
		type: String,
		default: ''
	}
}
<!--或者-->
this.$params.id

5.2,物件模式

在路由中設定props為物件,攜帶靜態資料

{
	path: '/vuex',
	name: 'Vuex',
	component: () => import('@/view/vuex'),
	props: {
		id: '99999'
	},
	mate: {
		title: 'vuex'
	}
}

跳轉

<router-link :to="{name:'Vuex'}" tag="h1">跳轉</router-link>
<!--或者-->
toNext() {
	this.$router.push({
		name: 'Vuex'
	})
}

在跳轉過去的頁面,通過props或者this.$params取參

props: {
	id: {
		type: String,
		default: ''
	}
}
<!--或者-->
this.$params.id

注意:只適用於靜態資料

5.3,函式模式

先在路由中設定propsFunctionreturn一個物件,不管是query傳參還是params傳參,都可以轉為props

{
	path: '/vuex',
	name: 'Vuex',
	component: () => import('@/view/vuex'),
	props: route => ({
	    <!--query-->
		id: route.query.id,
		<!--params-->
		age: route.params.age
	}),
	mate: {
		title: 'vuex'
	}
}

跳轉

<router-link :to="{name:'Vuex',query: {id: '99999'}, params:{age:'20'}}" tag="h1">跳轉</router-link>
<!--或者-->
toNext() {
	this.$router.push({
		name: 'Vuex',
		query: {
			id: '999999'
		},
		params: {
			age: '20'
		}
	})
}

在跳轉過去的頁面,通過props或者this.$route.params / this.$route.query取參

props: {
	id: {
		type: String,
		default: ''
	},
	age: {
		type: String,
		default: ''
	}
}
<!--或者-->
this.$route.query
this.$route.params

6,路由守衛

路由守衛主要用來通過跳轉或取消的方式守衛導航。

6.1,全域性前置守衛beforeEach

當一個導航觸發時,全域性前置守衛按照建立順序呼叫。守衛是非同步解析執行,此時導航在所有守衛解析完之前一直處於等待中。

引數 說明
to 即將要進入的目標路由物件
from 當前導航正要離開的路由
next 回撥方法

next用法如下

語法 說明
next() 進行下一個鉤子
next(false) 中斷導航,URL如已改,則重置到from的地址
next('/') 中斷當前跳轉併到其他地址,可設定路由物件
next(error) 導航終止並傳遞錯誤給onError()
const router = new VueRouter({ ... })

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

6.2,全域性解析守衛beforeResolve

2.5.0新增,和beforeEach類似,區別是在導航被確認之前,同時在所有元件內守衛和非同步路由元件被解析之後,解析守衛就被呼叫。

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

6.3,全域性後置鉤子afterEach

後置守衛不會接受next函式也不會改變導航本身

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

6.4,路由獨享守衛beforeEnter

可以在路由配置上直接定義專屬的beforeEnter守衛,與全域性前置守衛的方法引數是一樣的。

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

6.5,元件內的守衛

  • beforeRouteEnter

該守衛不能訪問this,因為守衛在導航確認前被呼叫,因此即將登場的新元件還沒被建立。可以通過傳一個回撥給next來訪問元件例項。在導航被確認的時候執行回撥,並且把元件例項作為回撥方法的引數。

const Footer = {
  template: `...`,
  beforeRouteEnter(to, from, next) {
    next(vm => {
        // 通過 `vm` 訪問元件例項
    })
  }
}
  • beforeRouteUpdate (2.2 新增)

在當前路由改變,但是該元件被複用時呼叫,可以訪問元件例項this

const Foo = {
  template: `...`,
  beforeRouteUpdate(to, from, next) {
    this.name = to.params.name
    next()
  }
}
  • beforeRouteLeave

導航離開該元件的對應路由時呼叫,通常用來禁止使用者在還未儲存修改前突然離開。可以通過next(false)來取消。

const Foo = {
  template: `...`,
  beforeRouteLeave(to, from, next) {
    const answer = window.confirm('確認要離開嗎')
    if (answer) {
        next()
    } else {
        next(false)
    }
  }
}

6.6,完整的導航解析流程

  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的回撥函式,建立好的元件例項會作為回撥函式的引數傳入。

7,路由元資訊

定義路由的時候可以配置meta物件欄位,用來儲存每個路由對應的資訊。通過this.$route.meta來訪問,或者在路由守衛中通過to.metafrom.meta訪問。

const router = new VueRouter({
  routes: [
    {
		path: '/index',
		name: 'Index',
		component: () => import('@/view/index'),
		meta: {
			title: '首頁',
			rolu: ['admin', 'boss']
		}
	}
  ]
})

8,過渡動效

只需要使用transition標籤包裹住router-view標籤即可,動畫效果可以自己定義,參考transition元件的用法。也可以在父元件或者app.js中使用watch監聽$route變化,根據不同路由替換transition元件的name屬性,實現不同的動畫效。

<transition :name="transitionName">
  <router-view></router-view>
</transition>

監聽

watch: {
  '$route' (to, from) {
    const toD = to.path.split('/').length
    const fromD = from.path.split('/').length
    this.transitionName = toD < fromD ? 'slide-right' : 'slide-left'
  }
}

9,滾動行為

當建立Router例項時,可以提供一個scrollBehavior方法,並接收tofrom路由物件。第三個引數savedPosition只有通過瀏覽器的前進/後退按鈕觸發時才可用。

const router = new VueRouter({
	mode: 'hash',
	routes,
	scrollBehavior(to, from, savedPosition) {
		if (savedPosition) {
			return new Promise((resolve, reject) => {
				setTimeout(() => {
					resolve(savedPosition)
				}, 1000)
			})
		} else {
			return { x: 0, y: 0 }
		}
	}
})

10,完整路由配置

首先匯入Vuevue-router,然後使用router,定義路由資訊集合,每個路由都是一個物件,物件擁有如下屬性

屬性 型別
path String 元件路徑資訊
name String 元件命名
component Function 元件
mate Object 元資訊
children Object 子路由
redirect String 重定向
props Boolean/Object/Function 引數傳遞

具體程式碼如下:

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

const routes = [
	{
		path: '/',
		redirect: '/index'
	},
	{
		path: '/index',
		name: 'Index',
		component: () => import(/* webpackChunkName: "index" */ '@/view/index'),
		mate: {
			title: '首頁',
			auth: false
		}
	},
	{
		path: '/login',
		name: 'Login',
		component: () => import(/* webpackChunkName: "login" */ '@/view/login'),
		meta: {
			title: '登入',
			auth: false
		},
		children: [
			{
				path: 'children',
				name: 'Children',
				component: () => import(/* webpackChunkName: "children" */ '@/view/children'),
				mate: {
					title: '巢狀的子路由',
					auth: false
				}
			}
		]
	}
]

const router = new VueRouter({
	mode: 'hash',
	routes
})

export default router

注意:巢狀子路由必須在被巢狀的頁面放置<router-view>標籤。

如果看了覺得有幫助的,我是@鵬多多,歡迎 點贊 關注 評論;END

面向百度程式設計

公眾號

weixinQRcode.png

往期文章

個人主頁

相關文章