路由中有三個(gè)基本的概念 route, routes, router:
1, route,它是一條路由,由這個(gè)英文單詞也可以看出來,它是單數(shù), Home按鈕 => home內(nèi)容, 這是一條route, about按鈕 => about 內(nèi)容, 這是另一條路由。
2, routes 是一組路由,把上面的每一條路由組合起來,形成一個(gè)數(shù)組。[{home 按鈕 =>home內(nèi)容 }, { about按鈕 => about 內(nèi)容}]
3, router 是一個(gè)機(jī)制,相當(dāng)于一個(gè)管理者,它來管理路由。因?yàn)閞outes 只是定義了一組路由,它放在哪里是靜止的,當(dāng)真正來了請(qǐng)求,怎么辦? 就是當(dāng)用戶點(diǎn)擊home 按鈕的時(shí)候,怎么辦?這時(shí)router 就起作用了,它到routes 中去查找,去找到對(duì)應(yīng)的 home 內(nèi)容,所以頁面中就顯示了 home 內(nèi)容。
4,客戶端中的路由,實(shí)際上就是dom 元素的顯示和隱藏。當(dāng)頁面中顯示home 內(nèi)容的時(shí)候,about 中的內(nèi)容全部隱藏,反之也是一樣。客戶端路由有兩種實(shí)現(xiàn)方式:基于hash 和基于html5 history api.
路由跳轉(zhuǎn)等都需要vue-router
active-class是vue-router模塊的router-link組件中的屬性,用來做選中樣式的切換;
在router目錄下的index.js文件中,對(duì)path屬性加上/:id
使用router對(duì)象的params.id 例如 : this.$route.params.id
vue-router 的導(dǎo)航鉤子,主要用來作用是攔截導(dǎo)航,讓他完成跳轉(zhuǎn)或取消。
有三種方式可以植入路由導(dǎo)航過程中:
1.全局的
2.單個(gè)路由獨(dú)享的
3組件級(jí)的
全局導(dǎo)航鉤子主要有兩種鉤子:前置守衛(wèi)、后置鉤子,
注冊(cè)一個(gè)全局前置守衛(wèi):
const router = new VueRouter({ ... });
router.beforeEach((to, from, next) => {
// do someting
});
這三個(gè)參數(shù) to 、from 、next 分別的作用:
1.to: Route,代表要進(jìn)入的目標(biāo),它是一個(gè)路由對(duì)象
2.from: Route,代表當(dāng)前正要離開的路由,同樣也是一個(gè)路由對(duì)象
3.next: Function,這是一個(gè)必須需要調(diào)用的方法,而具體的執(zhí)行效果則依賴 next 方法調(diào)用的參數(shù)(next函數(shù)必須調(diào)用)
1).next():進(jìn)入管道中的下一個(gè)鉤子,如果全部的鉤子執(zhí)行完了,則導(dǎo)航的狀態(tài)就是 confirmed(確認(rèn)的)
2).next(false):這代表中斷掉當(dāng)前的導(dǎo)航,即 to 代表的路由對(duì)象不會(huì)進(jìn)入,被中斷,此時(shí)該表 URL 地址會(huì) 被重置到 from 路由對(duì)應(yīng)的地址
3).next(‘/’) 和 next({path: ‘/’}):在中斷掉當(dāng)前導(dǎo)航的同時(shí),跳轉(zhuǎn)到一個(gè)不同的地址
4).next(error):如果傳入?yún)?shù)是一個(gè) Error 實(shí)例,那么導(dǎo)航被終止的同時(shí)會(huì)將錯(cuò)誤傳遞給 router.onError() 注冊(cè)過的回調(diào)
后置鉤子注冊(cè):
router.afterEach((to, from) => {
// do someting
});
沒有next()函數(shù)
在路由配置上定義,其參數(shù)的使用,和全局前置守衛(wèi)是一樣的
const router = new VueRouter({
routes: [
{
path: '/file',
component: File,
beforeEnter: (to, from ,next) => {
// do someting
}
}
]
});
組件內(nèi)的導(dǎo)航鉤子主要有這三種:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。他們是直接在路由組件內(nèi)部直接進(jìn)行定義的
const File = {
template: `<div>This is file</div>`,
beforeRouteEnter(to, from, next) {
// do someting
// 在渲染該組件的對(duì)應(yīng)路由被 confirm 前調(diào)用
},
beforeRouteUpdate(to, from, next) {
// do someting
// 在當(dāng)前路由改變,但是依然渲染該組件是調(diào)用
},
beforeRouteLeave(to, from ,next) {
// do someting
// 導(dǎo)航離開該組件的對(duì)應(yīng)路由時(shí)被調(diào)用
}
}
1、切換路由,路由參數(shù)發(fā)生了變化,但是頁面數(shù)據(jù)并未及時(shí)更新,需要強(qiáng)制刷新后才會(huì)變化。
2、不同路由渲染相同的組件時(shí)(組件復(fù)用比銷毀重新創(chuàng)建效率要高),在切換路由后,當(dāng)前組件下的生命周期函數(shù)不會(huì)再被調(diào)用。
解決方案:
1、使用 watch 監(jiān)聽 $route
watch: {
$route(to, from){
if(to != from) {
console.log("監(jiān)聽到路由變化,做出相應(yīng)的處理");
}
}
}
2、向 router-view 組件中添加 key
<router-view :key="$route.fullPath"></router-view>
$route.fullPath 是完成后解析的URL,包含其查詢參數(shù)信息和hash完整路徑
vue-router有兩種模式,hash模式和history模式
hash模式背后的原理是onhashchange事件,可以在window對(duì)象上監(jiān)聽這個(gè)事件.
隨著history api的到來,前端路由開始進(jìn)化了,前面的hashchange,你只能改變#后面的url片段,而history api則給了前端完全的自由.
通過history api,我們丟掉了丑陋的#,但是它也有個(gè)毛病:
在hash模式下,前端路由修改的是#中的信息,而瀏覽器請(qǐng)求時(shí)是不帶它玩的,所以沒有問題.但是在history下,你可以自由的修改path,當(dāng)刷新時(shí),如果服務(wù)器中沒有相應(yīng)的響應(yīng)或者資源,會(huì)分分鐘刷出一個(gè)404來。
vue異步組件
es提案的import()
webpack的require,ensure()
vue異步組件:
/* vue異步組件技術(shù) */
{
path: '/home',
name: 'home',
component: resolve => require(['@/components/home'],resolve)
},{
path: '/index',
name: 'Index',
component: resolve => require(['@/components/index'],resolve)
},{
path: '/about',
name: 'about',
component: resolve => require(['@/components/about'],resolve)
}
es提案的import():
// 下面2行代碼,指定了相同的webpackChunkName,會(huì)合并打包成一個(gè)js文件。 把組件按組分塊
const Home = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/home')
const Index = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/index')
const About = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/about')
{
path: '/about',
component: About
}, {
path: '/index',
component: Index
}, {
path: '/home',
component: Home
}
webpack的require,ensure():
/* 組件懶加載方案三: webpack提供的require.ensure() */
{
path: '/home',
name: 'home',
component: r => require.ensure([], () => r(require('@/components/home')), 'demo')
}, {
path: '/index',
name: 'Index',
component: r => require.ensure([], () => r(require('@/components/index')), 'demo')
}, {
path: '/about',
name: 'about',
component: r => require.ensure([], () => r(require('@/components/about')), 'demo-01')
}
和方法一的區(qū)別是 使用vue的異步組件技術(shù)時(shí)一個(gè)組件生成一個(gè)js文件,webpack提供的require.ensure(),多個(gè)路由指定相同的chunkName,會(huì)合并打包成一個(gè)js文件。