vue-router

首先拋出這樣一個(gè)問題,vue-router是用來做什么的?

這里不著急回答,也不準(zhǔn)備在這篇文章里回答。這篇文章僅總結(jié)一些使用心得,其實(shí)總結(jié)完所有關(guān)于vue-router的內(nèi)容后,整篇文章也許就剛好能回答這個(gè)問題了。

一 使用步驟

單純使用Vue.js,我們可以通過組合組件來組成應(yīng)用,不同的頁面有不同的地址,路由依靠鏈接跳轉(zhuǎn)。這顯然不是單頁應(yīng)用,因?yàn)闀?huì)有頁面刷新。

當(dāng)要把vue-router引入進(jìn)來,我們需要做的是,將組件映射到路由,然后告訴路由在哪里渲染組件內(nèi)容。

1. HTML

vue-router

Hello World!


toUser


2. JavaScript

importVuefrom'vue';

importVueRouterfrom'vue-router';

importindexPagefrom'./index.vue';

importuserPagefrom'./user.vue';

// 注冊(cè)路由插件

Vue.use(VueRouter);

// 配置路由

constroutes=[

{

path:'',

component:indexPage,

},{

path:'/user',

component:userPage,

}];

// 創(chuàng)建Router實(shí)例

constrouter=newVueRouter({

routes,

});

// 創(chuàng)建和掛載Vue根實(shí)例

constapp=newVue({

router,

});

app.$mount('#app');

router-link和router-view是兩個(gè)功能性內(nèi)置組件。router-link默認(rèn)被渲染為a標(biāo)簽,負(fù)責(zé)路由跳轉(zhuǎn)功能;router-view是組件內(nèi)容被渲染的位置。

js方面代碼里的注釋已經(jīng)寫得很清楚。

二 動(dòng)態(tài)路由

動(dòng)態(tài)路由其實(shí)又可以叫做路由傳參。

constrouter=newVueRouter({

routes:[

// 動(dòng)態(tài)路徑參數(shù) 以冒號(hào)開頭

{path:'/user/:id',component:User}

]

})

形如上述形式的路徑即為動(dòng)態(tài)路由,冒號(hào)后是參數(shù),可以跟多段參數(shù),每個(gè)參數(shù)都被設(shè)置到this.$route.params中。

注意/user/:id和/user/:name,當(dāng)參數(shù)變化時(shí),組件會(huì)被復(fù)用,因此組件生命周期鉤子不會(huì)被再次調(diào)用。復(fù)用組建時(shí),可以通過監(jiān)聽$route對(duì)象的變化來監(jiān)測(cè)路由是否變化。

路由鉤子beforeRouterUpdate也會(huì)執(zhí)行。

vue-router 使用path-to-regexp作為路徑匹配引擎,假如路徑很復(fù)雜可以學(xué)習(xí)高級(jí)的匹配模式。但是路徑一般不應(yīng)設(shè)計(jì)的太復(fù)雜,如果太復(fù)雜,應(yīng)該考慮如何簡(jiǎn)化。

三 命名視圖

有時(shí)候想同時(shí)(同級(jí))展示多個(gè)視圖,例如創(chuàng)建一個(gè)布局,有 sidebar(側(cè)導(dǎo)航) 和 main(主內(nèi)容)

兩個(gè)視圖,這個(gè)時(shí)候命名視圖就派上用場(chǎng)了。你可以在界面中擁有多個(gè)單獨(dú)命名的視圖,而不是只有一個(gè)單獨(dú)的出口。如果 router-view

沒有設(shè)置名字,那么默認(rèn)為 default。

一個(gè)視圖使用一個(gè)組件渲染,因此對(duì)于同個(gè)路由,多個(gè)視圖就需要多個(gè)組件。確保正確使用 components 配置(帶上 s):

routes:[

{

path:'/',

components:{

default:Foo,

a:SideBar,

b:Header

}

}

]

四 路由元信息

定義路由的時(shí)候可以配置 meta 字段:

routes:[

{

path:'/foo',

component:Foo,

children:[

{

path:'bar',

component:Bar,

// a meta field

meta:{requiresAuth:true}

}

]

}

]

五 編程式導(dǎo)航

除了使用 創(chuàng)建 a 標(biāo)簽來定義導(dǎo)航鏈接,我們還可以借助 router 的實(shí)例方法,通過編寫代碼來實(shí)現(xiàn)。

router.push(location)

想要導(dǎo)航到不同的 URL,則使用 router.push 方法。這個(gè)方法會(huì)向 history 棧添加一個(gè)新的記錄,所以,當(dāng)用戶點(diǎn)擊瀏覽器后退按鈕時(shí),則回到之前的 URL。

當(dāng)你點(diǎn)擊 時(shí),這個(gè)方法會(huì)在內(nèi)部調(diào)用,所以說,點(diǎn)擊 等同于調(diào)用 router.push(...)。

router.replace(location)

跟 router.push 很像,唯一的不同就是,它不會(huì)向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當(dāng)前的 history 記錄。

router.go(n);

這個(gè)方法的參數(shù)是一個(gè)整數(shù),意思是在 history 記錄中向前或者后退多少步,類似 window.history.go(n)。

六 懶加載

當(dāng)打包構(gòu)建應(yīng)用時(shí),Javascript 包會(huì)變得非常大,影響頁面加載。如果我們能把不同路由對(duì)應(yīng)的組件分割成不同的代碼塊,然后當(dāng)路由被訪問的時(shí)候才加載對(duì)應(yīng)組件,這樣就更加高效了。

異步組件模式:

constFoo=resolve =>{

// require.ensure 是 Webpack 的特殊語法,用來設(shè)置 code-split point

// (代碼分塊)

require.ensure(['./Foo.vue'],()=>{

resolve(require('./Foo.vue'))

})

}

Amd風(fēng)格的require模式:

constroutes=[

{

path:'',

component:resolve =>require(['./index.vue'],resolve),

},{

path:'/user',

component:resolve =>require(['./user.vue'],resolve),

}];

ensure模式寫起來有點(diǎn)繁瑣,我更傾向于后面一種寫法。

七 導(dǎo)航鉤子

鉤子(Hook),早期編程可能有個(gè)概念叫句柄,不知道將兩者類比而且強(qiáng)行歸為一類是不是合適。鉤子的用處是在某個(gè)特定流程中的不同時(shí)機(jī)暴露出一些函數(shù),使得用戶可以通過覆寫這些函數(shù)實(shí)現(xiàn)在原有位置執(zhí)行自己的代碼邏輯的功能。

1. 分類

vue-router中的導(dǎo)航鉤子按定義位置不同(執(zhí)行時(shí)機(jī)也不同)分為全局鉤子路由級(jí)鉤子組件級(jí)鉤子

全局鉤子

全局鉤子有三個(gè),分別是beforeEach、beforeResolve和afterEach,在路由實(shí)例對(duì)象注冊(cè)使用;

路由級(jí)鉤子

路由級(jí)鉤子有beforeEnter,在路由配置項(xiàng)中項(xiàng)定義;

組件級(jí)鉤子

組件級(jí)鉤子有beforeRouteEnter、beforeRouteUpdate和beforeRouteLeave,在組件屬性中定義;

2. 代碼示例

import Vue from 'vue';

import VueRouter from 'vue-router';

// Vue中插件必須use注冊(cè)

Vue.use(VueRouter);

// 路由配置項(xiàng),此處是路由級(jí)鉤子的定義

const routes = [{

? ? ? ? path: '/',

? ? ? ? component: resolve => require(['./index.vue'], resolve),

? ? ? ? keepAlive: true,

? ? },

? ? {

? ? ? ? path: '/user/:userName',

? ? ? ? keepAlive: true,

? ? ? ? beforeEnter(to,from,next){

? ? ? ? ? ? console.log('router beforeEnter');

? ? ? ? ? ? next();

? ? ? ? },

? ? ? ? component: resolve => require(['./user.vue'], resolve),

? ? }];

// 實(shí)例化路由對(duì)象

const router = new VueRouter({

? ? routes

});

// 全局鉤子

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

? ? console.log('global beforeEach')

? ? next();

});

router.beforeResolve((to,from,next)=>{

? ? console.log('global beforeResolve')

? ? next();

});

router.afterEach((to,from,next)=>{

? ? console.log('global afterEach')

});

// 實(shí)例化Vue對(duì)象并掛載

new Vue({

? ? router

}).$mount('#app');

user.vue

? ?

? ? ? ?

{{ msg }}

? ? ? ?

我是:{{userName}}


? ? export default {

? ? ? ? name: 'user',

? ? ? ? data () {

? ? ? ? ? ? return {

? ? ? ? ? ? ? ? msg: '這里是 User Page.',

? ? ? ? ? ? ? ? userName: '葉落'

? ? ? ? ? ? };

? ? ? ? },

? ? ? ? methods: {},

? ? ? ? mounted () {

? ? ? ? ? ? var me = this;

? ? ? ? ? ? me.userName = me.$route.params.userName;

? ? ? ? ? ? console.log('user mounted.');

? ? ? ? },

? ? ? ? beforeRouteEnter (to, from, next) {

? ? ? ? ? ? console.log('component beforeRouteEnter');

? ? ? ? ? ? next();

? ? ? ? },

? ? ? ? beforeRouteUpdate (to, from, next) {

? ? ? ? ? ? console.log('component beforeRouteUpdate');

? ? ? ? ? ? next();

? ? ? ? },

? ? ? ? beforeRouteLeave(to,from,next){

? ? ? ? ? ? console.log('component beforeRouteLeave');

? ? ? ? ? ? next();

? ? ? ? }

? ? };

3. 執(zhí)行時(shí)機(jī)

由首頁進(jìn)入user頁面:

global beforeEach > router beforeEnter > component

beforeRouteEnter > global beforeResolve > global afterEach >

mounted

由user回到首頁:

component beforeRouteLeave => global beforeEach => global beforeResolve => global afterEach

排除beforeRouteUpdate,其余六個(gè)導(dǎo)航鉤子的執(zhí)行時(shí)機(jī)其實(shí)很好理解。大體按照leave、before、enter、resolve、after的順序并全局優(yōu)先的思路執(zhí)行。beforeRouteUpdate的觸發(fā)是在動(dòng)態(tài)路由情形下,比如

path: '/user/:userName'

這條路由,當(dāng)頁面不變更只動(dòng)態(tài)的改變參數(shù)userName時(shí),beforeRouteUpdate便會(huì)觸發(fā)。

總結(jié):使用vue組件拼湊成整個(gè)應(yīng)用,每個(gè)頁面是獨(dú)立的,路由依靠鏈接跳轉(zhuǎn),會(huì)刷新頁面。使用vue-router則可以不刷新頁面加載對(duì)應(yīng)組件,hash和history模式模擬路徑變化,不刷新頁面。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • xbm524閱讀 359評(píng)論 0 1
  • 你好,回來了??吹叫づ孔哌M(jìn)小區(qū)大門,我打了聲招呼。她挽著一個(gè)男人的手,用微笑表示回應(yīng)。肖女士今天穿的是超短裙,真...
    野外一匹馬閱讀 2,777評(píng)論 0 5

友情鏈接更多精彩內(nèi)容