路由
注入實(shí)例
const router = new VueRouter({
routes : [
{ path: '/user', name: 'user' , component: { template: '<div>User</div>' },
{ path: '/user/:id',
component: { template: '<div>{{ $route.params.id }}</div>' }
}
]
})
new Vue({
router
}).$mount('#app')
此后可以在任何組件內(nèi)通過(guò) this.$router
訪(fǎng)問(wèn)路由器(或通過(guò)import導(dǎo)入router實(shí)例來(lái)訪(fǎng)問(wèn)),通過(guò) this.$route
訪(fǎng)問(wèn)當(dāng)前路由(包括query,hash等)
路由參數(shù)
通過(guò):
標(biāo)記路由參數(shù),組件內(nèi)可通過(guò)$route.params
訪(fǎng)問(wèn)該參數(shù)。
使用props可以將組件和路由解耦,使組件不再只能在特定URL下使用。
嵌套路由
如下,當(dāng) /main 匹配成功,Main會(huì)被渲染,同時(shí) MainDefault 會(huì)被渲染在 Main 的<router-view> 中。當(dāng)/main/dashboard 匹配成功,Dashboard 會(huì)被渲染在 Main 的<router-view> 中
{
path: '/main',
name: 'main',
component: Main,
children: [
{ path: '', component: MainDefault },
{
path: 'dashboard',
component: Dashboard
}
]
}
捕獲所有路由或404路由
通過(guò)通配符 *
可匹配所有路徑,如需匹配404則應(yīng)將該路由配置在最后(先配置的路由匹配優(yōu)先級(jí)更高)
{
path: '*'
}
history模式
利用了history.pushState API
,使URL中將不再具有#
。但需服務(wù)器端做好對(duì)應(yīng)配置。
const router = new VueRouter({
mode: 'history',//默認(rèn)為hash
routes: [...]
})
重定向
重定向需要精準(zhǔn)匹配(如父子路由都配置了redirect,且此時(shí)跳向子路由,則只會(huì)觸發(fā)子的redirect)
導(dǎo)航守衛(wèi)只會(huì)對(duì)重定向之后的路由生效
routes: [
{ path: '/a', redirect: '/bar' },
{ path: '/b', redirect: { name: 'foo' }}
]
別名
/a 的別名是 /b,意味著,當(dāng)用戶(hù)訪(fǎng)問(wèn) /b 時(shí),URL 會(huì)保持為 /b,但是路由匹配則為 /a,就像用戶(hù)訪(fǎng)問(wèn) /a 一樣。
{ path: '/a', component: A, alias: '/b' }
導(dǎo)航和出口
<router-link>
默認(rèn)會(huì)被渲染成一個(gè) <a>
標(biāo)簽,將匹配到的組件渲染在路由出口<router-view>
以 / 開(kāi)頭的嵌套路徑會(huì)被當(dāng)作根路徑
<router-link to="/foo">Go to Foo</router-link>
<router-view></router-view>
編程式的導(dǎo)航
-
router.push(location, onComplete?, onAbort?)
location
可以為對(duì)象或字符串。注意當(dāng)對(duì)象使用path
時(shí),params
會(huì)被忽略。
同樣的規(guī)則也適用于router-link
組件的to
屬性。
// 字符串
router.push('home')
// 對(duì)象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 帶查詢(xún)參數(shù),變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
onComplete
和onAbort
回調(diào)將會(huì)在導(dǎo)航成功完成 (在所有的異步鉤子被解析之后) 或終止 (導(dǎo)航到相同的路由、或在當(dāng)前導(dǎo)航完成之前導(dǎo)航到另一個(gè)不同的路由) 的時(shí)候進(jìn)行相應(yīng)的調(diào)用
-
router.replace(location, onComplete?, onAbort?)
不會(huì)向 history 添加新記錄 -
router.go(n)
傳入-1時(shí)即為后退
命名出口
同一層級(jí)下存在多個(gè)視圖,可通過(guò)name
區(qū)分,默認(rèn)為default
<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
}
}
]
})
導(dǎo)航守衛(wèi)
觸發(fā)條件
路由參數(shù)(如:id)或查詢(xún)(query)的改變會(huì)復(fù)用組件,并不會(huì)觸發(fā)進(jìn)入/離開(kāi)的導(dǎo)航守衛(wèi),也不會(huì)銷(xiāo)毀/創(chuàng)建目標(biāo)組件。因此組件的生命周期也不會(huì)觸發(fā)。此時(shí)可以通過(guò)以下方式相應(yīng)路由參數(shù)變化:
- watch
$route
對(duì)象 - 組件內(nèi)導(dǎo)航守衛(wèi)
beforeRouteUpdate (to, from, next) {}
觸發(fā)順序
導(dǎo)航被觸發(fā)。
在失活的組件里調(diào)用離開(kāi)守衛(wèi)。beforeRouteLeave
如此時(shí)發(fā)生redirect,以下內(nèi)容只會(huì)對(duì)redirect后的路由生效
進(jìn)入路由時(shí)如果為嵌套路由,則總是先觸發(fā)父組件的相應(yīng)守衛(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ù)。
全局前置守衛(wèi) router.beforeEach
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
當(dāng)一個(gè)導(dǎo)航觸發(fā)時(shí),全局前置守衛(wèi)按照創(chuàng)建順序調(diào)用。守衛(wèi)是異步解析執(zhí)行,此時(shí)導(dǎo)航在所有守衛(wèi) resolve 完之前一直處于 等待中。
每個(gè)守衛(wèi)方法接收三個(gè)參數(shù):
-
to: Route
: 即將要進(jìn)入的目標(biāo)路由 -
from: Route
: 當(dāng)前導(dǎo)航正要離開(kāi)的路由 -
next: Function
: 一定要調(diào)用該方法來(lái) resolve 這個(gè)鉤子。執(zhí)行效果依賴(lài)next
方法的調(diào)用參數(shù)。next()
: 進(jìn)行管道中的下一個(gè)鉤子。如果全部鉤子執(zhí)行完了,則導(dǎo)航的狀態(tài)就是 confirmed (確認(rèn)的)。next(false)
: 中斷當(dāng)前的導(dǎo)航。如果瀏覽器的 URL 改變了 (可能是用戶(hù)手動(dòng)或者瀏覽器后退按鈕),那么 URL 地址會(huì)重置到from
路由對(duì)應(yīng)的地址。next('/')
或者next({ path: '/' })
: 跳轉(zhuǎn)到一個(gè)不同的地址。當(dāng)前的導(dǎo)航被中斷,然后進(jìn)行一個(gè)新的導(dǎo)航。你可以向next
傳遞任意位置對(duì)象,且允許設(shè)置諸如replace: true
、name: 'home'
之類(lèi)的選項(xiàng)以及任何用在router-link
的to
prop 或router.push
中的選項(xiàng)。next(error)
: (2.4.0+) 如果傳入next
的參數(shù)是一個(gè)Error
實(shí)例,則導(dǎo)航會(huì)被終止且該錯(cuò)誤會(huì)被傳遞給router.onError()
注冊(cè)過(guò)的回調(diào)。
確保要調(diào)用next
方法,否則鉤子就不會(huì)被 resolved。
全局解析守衛(wèi) router.beforeResolve
和 router.beforeEach
類(lèi)似,區(qū)別是在導(dǎo)航被確認(rèn)之前,同時(shí)在所有組件內(nèi)守衛(wèi)和異步路由組件被解析之后,解析守衛(wèi)就被調(diào)用。
全局后置鉤子 afterEach
不會(huì)接受 next 函數(shù)也不會(huì)改變導(dǎo)航本身
router.afterEach((to, from) => {
// ...
})
路由獨(dú)享的守衛(wèi) beforeEnter
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
組件內(nèi)守衛(wèi)
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對(duì)應(yīng)路由被 confirm 前調(diào)用
// 不!能!獲取組件實(shí)例 `this`,因?yàn)楫?dāng)守衛(wèi)執(zhí)行前,組件實(shí)例還沒(méi)被創(chuàng)建
next(vm => {
// 但是可以通過(guò)回調(diào)中的 `vm` 訪(fǎng)問(wèn)組件實(shí)例
})
},
beforeRouteUpdate (to, from, next) {
// 在當(dāng)前路由改變,但是該組件被復(fù)用時(shí)調(diào)用
// 舉例來(lái)說(shuō),對(duì)于一個(gè)帶有動(dòng)態(tài)參數(shù)的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉(zhuǎn)的時(shí)候,
// 由于會(huì)渲染同樣的 Foo 組件,因此組件實(shí)例會(huì)被復(fù)用。而這個(gè)鉤子就會(huì)在這個(gè)情況下被調(diào)用。
// 可以訪(fǎng)問(wèn)組件實(shí)例 `this`
},
beforeRouteLeave (to, from, next) {
// 導(dǎo)航離開(kāi)該組件的對(duì)應(yīng)路由時(shí)調(diào)用
// 可以訪(fǎng)問(wèn)組件實(shí)例 `this`
}
}
路由元信息 meta
可用于存儲(chǔ)該路由的一些自定義信息,如權(quán)限檢測(cè)、是否需要登錄等。
一個(gè)路由匹配到的所有路由記錄(包括所有祖先)會(huì)暴露為 $route.matched
數(shù)組。我們可以遍歷 $route.matched 來(lái)檢查路由記錄中的 meta 字段。
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
children: [
{
path: 'bar',
component: Bar,
meta: { requiresAuth: true }
}
]
}
]
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!auth.loggedIn()) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // 確保一定要調(diào)用 next()
}
})
滾動(dòng)行為
換到新路由時(shí),想要頁(yè)面滾到指定位置,或者是保持原先的滾動(dòng)位置,或滾動(dòng)到目標(biāo)錨點(diǎn)。
const router = new VueRouter({
routes: [...],
scrollBehavior (to, from, savedPosition) {
// return 期望滾動(dòng)到哪個(gè)的位置
// `savedPosition` 當(dāng)且僅當(dāng) popstate 導(dǎo)航 (通過(guò)瀏覽器的 前進(jìn)/后退 按鈕觸發(fā)) 時(shí)才可用。
}
})
路由懶加載
把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊,當(dāng)路由被訪(fǎng)問(wèn)的時(shí)候才加載對(duì)應(yīng)組件
Webpack自動(dòng)分割
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
把組件按組分塊
通過(guò)命名chunk
,一個(gè)特殊的注釋語(yǔ)法,Webpack 會(huì)將相同塊名稱(chēng)的異步模塊組合到相同的異步塊中。
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')