新聞中心
1.路由的起源
服務(wù)端控制的路由來(lái)實(shí)現(xiàn)服務(wù)端渲染,服務(wù)端渲染的優(yōu)缺點(diǎn)在于:

創(chuàng)新互聯(lián)建站是一家集網(wǎng)站建設(shè),尼元陽(yáng)企業(yè)網(wǎng)站建設(shè),尼元陽(yáng)品牌網(wǎng)站建設(shè),網(wǎng)站定制,尼元陽(yáng)網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,尼元陽(yáng)網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
- 優(yōu)點(diǎn):安全性好,便于SEO,能夠提升前端頁(yè)面的渲染速度
- 缺點(diǎn):會(huì)增加服務(wù)器的壓力,代碼冗余不便于維護(hù),不利于用戶體驗(yàn)
服務(wù)端控制路由本質(zhì)是url和文件讀取操作的映射,而前端路由是進(jìn)行dom元素的顯示和隱藏操作,在訪問不同路徑時(shí)顯示不同的組件。當(dāng)前前端路由主要有兩種實(shí)現(xiàn)方式:hash模式和history模式。
前端路由的優(yōu)缺點(diǎn)在于:
- 缺點(diǎn):不利于SEO,使用瀏覽器的前進(jìn)、后退鍵時(shí)會(huì)重新發(fā)送請(qǐng)求,沒有合理的利用緩存
- 優(yōu)點(diǎn):良好的交互體驗(yàn),用戶不需要刷新頁(yè)面,頁(yè)面顯示流暢,良好的前后端工作分離模式,減輕服務(wù)器壓力
2.路由的兩種模式的區(qū)別和原理?
Vue-router有兩種路由模式,分別是hash模式和history模式,在路由配置中默認(rèn)的是hash模式。
hash模式
早期的前端路由是基于location.hash來(lái)實(shí)現(xiàn)的,對(duì)此在react-router和vue-router都是默認(rèn)將hash路由作為路由模式的。hash模式的url默認(rèn)帶有#,location.hash的值就是url的#后面的內(nèi)容。
在vue-router中,對(duì)于http://blog.onechuan.cn/#/login的hash值就是#/login。
特點(diǎn):
- hash值會(huì)存現(xiàn)客戶端的url中,但是不會(huì)出現(xiàn)在發(fā)送給服務(wù)端的http請(qǐng)求中,也就是hash不會(huì)被發(fā)送;
- hash值得改變,不會(huì)重新加載頁(yè)面,只是單純地在瀏覽器的訪問歷史中增加個(gè)記錄,其實(shí)就是在棧結(jié)構(gòu)中添加和移除數(shù)據(jù),來(lái)實(shí)現(xiàn)瀏覽器的回退和前進(jìn)控制hash的切換;
- hash模式對(duì)于瀏覽器的兼容性比較好,也是SPA單頁(yè)面應(yīng)用的標(biāo)配。
使用: 切換hash路由的方式有兩種
- 使用a標(biāo)簽設(shè)置href屬性,在用戶點(diǎn)擊后觸發(fā)改變url,也就是觸發(fā)hashchange事件search ;
- 直接使用js來(lái)實(shí)現(xiàn)對(duì)location.hash進(jìn)行賦值,從而實(shí)現(xiàn)改變url,觸發(fā)hashchange事件location.hash="#search"。
對(duì)此,可以看到hash路由的實(shí)現(xiàn)就是基于hashchange事件進(jìn)行監(jiān)聽。
原理:
hash模式的主要原理就是onhashchange()事件:
window.onhashchange = function(event){
console.log(event.oldURL, event.newURL);
let hash = location.hash.slice(1);
}使用onhashchange()的優(yōu)點(diǎn):
- 在頁(yè)面的hash值發(fā)生變化時(shí),無(wú)需向后端發(fā)起請(qǐng)求,window就可以監(jiān)聽事件的改變,并按規(guī)則加載相應(yīng)的代碼;
- hash值變化對(duì)應(yīng)的URL都會(huì)被瀏覽器記錄下來(lái),這樣瀏覽器就能實(shí)現(xiàn)頁(yè)面的前進(jìn)和后退。沒有請(qǐng)求后端服務(wù)器,但是頁(yè)面的hash值和對(duì)應(yīng)的URL關(guān)聯(lián)映射。
history模式
history模式的url中沒有#,看起來(lái)也比hash模式更美觀,本質(zhì)是通過(guò)傳統(tǒng)的路由分發(fā)模式,即用戶輸入一個(gè)url時(shí),服務(wù)器會(huì)接收請(qǐng)求并解析這個(gè)URL,然后做出相應(yīng)的邏輯處理。
當(dāng)使用history模式時(shí),URL就像這樣:https://blog.onechuan.cn/user/id。
特點(diǎn):
- history模式的url相對(duì)于hash模式而言,更加美觀;
- history模式需要服務(wù)端進(jìn)行相應(yīng)的配置支持,否則返回時(shí)會(huì)返回404;
- pushState 和 repalceState 的標(biāo)題(title):一般瀏覽器會(huì)忽略,最好傳入 null;
- 可以使用 popstate 事件來(lái)監(jiān)聽 url 的變化;
原理:
history模式主要依賴于:history.pushState()和 history.repalceState() 兩個(gè)api來(lái)實(shí)現(xiàn)不進(jìn)行刷新的情況下,操作瀏覽器的歷史記錄。
- 修改歷史狀態(tài):history.pushState()和 history.repalceState()提供了對(duì)歷史記錄進(jìn)行修改的功能。只是當(dāng)他們進(jìn)行修改時(shí),雖然修改了url,但瀏覽器不會(huì)立即向后端發(fā)送請(qǐng)求。如果要做到改變url但又不刷新頁(yè)面的效果,就需要前端用上這兩個(gè)API。
- 切換歷史狀態(tài):包括forward()、back()、go()三個(gè)方法,對(duì)應(yīng)瀏覽器的前進(jìn)、后退、跳轉(zhuǎn)操作
pushState和repalceState不會(huì)觸發(fā)popstate 事件,這時(shí)我們需要手動(dòng)觸發(fā)頁(yè)面渲染。
缺點(diǎn):在刷新頁(yè)面的時(shí)候,如果沒有相應(yīng)的路由或資源,就會(huì)刷出404來(lái)。
兩種路由模式的對(duì)比
|
對(duì)比點(diǎn) |
hash模式 |
history模式 |
|
原理 |
onhashchange() |
history.pushState()和 history.repalceState() |
|
兼容性 |
>= ie 8,其它主流瀏覽器 |
>= ie 10,其它主流瀏覽器 |
|
實(shí)用性 |
不需要對(duì)服務(wù)端做改動(dòng) |
需要服務(wù)端配置支持 |
3.如何獲取頁(yè)面的hash變化?
通過(guò)監(jiān)聽$route的變化
// 監(jiān)聽,當(dāng)路由發(fā)生變化的時(shí)候執(zhí)行
watch: {
$route: {
handler: function(val, oldVal){
console.log(val);
},
// 深度觀察監(jiān)聽
deep: true
}
}
通過(guò)js的window.location.hash讀取#值
window.location.hash 的值可讀可寫,讀取來(lái)判斷狀態(tài)是否改變,寫入時(shí)可以在不重載網(wǎng)頁(yè)的前提下,添加一條歷史訪問記錄。
4.Vue-Router如何實(shí)現(xiàn)路由懶加載?
使用箭頭函數(shù)+import動(dòng)態(tài)加載
const List = () => import('@/components/list.vue')
const router = new VueRouter({
routes: [
{ path: '/list', component: List }
]
});使用箭頭函數(shù)+require動(dòng)態(tài)加載
const router = new Router({
routes: [
{
path: '/list',
component: resolve => require(['@/components/list'], resolve)
}
]
});使用webpack的require.ensure技術(shù)
這種情況下,多個(gè)路由指定相同的chunkName,會(huì)合并打包成一個(gè)js文件。
// r就是resolve
const List = r => require.ensure([], () => r(require('@/components/list')), 'list');
// 路由也是正常的寫法 這種是官方推薦的寫的 按模塊劃分懶加載
const router = new Router({
routes: [
{
path: '/list',
component: List,
name: 'list'
}
]
}));
5.$route 和$router 的區(qū)別?
$route 是“路由信息對(duì)象”,包括 path、params hash、query、fullPath、matched、name 等路由信息參數(shù);
$router 是“路由實(shí)例”對(duì)象包括了路由的跳轉(zhuǎn)方法,鉤子函數(shù)等。
6.如何定義動(dòng)態(tài)路由?如何獲取傳過(guò)來(lái)的動(dòng)態(tài)參數(shù)?
param方式
配置路由格式:/router/:id
- 傳遞方式:在path后面跟上對(duì)應(yīng)的值
- 傳遞后形成的路徑:/router/123
定義動(dòng)態(tài)路由
//在APP.vue中用戶
//在router.js
{
path: '/user/:userid',
component: User,
}
路由跳轉(zhuǎn)
// 方法1:按鈕
// 方法2:
this.$router.push({name:'users',params:{uname:onechuan}})
// 方法3:
this.$router.push(`/user/${onechuan}`);
參數(shù)獲取通過(guò) $route.params.userid 獲取傳遞的值。
query方式
- 配置路由格式:/router,也就是普通配置
- 傳遞方式:對(duì)象中使用query的key作為傳遞方式
- 傳遞后形成的路徑:/route?id=123
路由定義
//方式1:直接在router-link 標(biāo)簽上以對(duì)象的形式檔案
// 方式2:寫成按鈕以點(diǎn)擊事件形式
profileClick(){
this.$router.push({
path: "/profile",
query: {
name: "kobi",
age: "28",
height: 198
}
});
}
跳轉(zhuǎn)方法
// 方法1:按鈕
// 方法2:
this.$router.push({ name: 'users', query:{ uname:james }})
// 方法3:按鈕
// 方法4:
this.$router.push({ path: '/user', query:{ uname:james }})
// 方法5:
this.$router.push('/user?uname=' + james)
獲取參數(shù)通過(guò)$route.query 獲取傳遞的值。
7.params和query的區(qū)別?
|
對(duì)比點(diǎn) |
params |
query |
|
引入方式 |
用name來(lái)引入 |
用path來(lái)引入 |
|
接收參數(shù) |
this.$route.params.name |
this.$route.query.name |
|
url地址顯示 |
params則類似于post,url不顯示參數(shù) |
query更加類似于ajax中g(shù)et傳參,url顯示參數(shù) |
|
刷新頁(yè)面 |
params刷新會(huì)丟失 params里面的數(shù)據(jù) |
query刷新不會(huì)丟失query里面的數(shù)據(jù) |
8.Vue-router 路由鉤子在生命周期的體現(xiàn)?
完整的路由導(dǎo)航解析流程(不包括其他生命周期)
- 觸發(fā)進(jìn)入其他路由。
- 調(diào)用要離開路由的組件守衛(wèi)beforeRouteLeave
- 調(diào)用局前置守衛(wèi)∶ beforeEach
- 在重用的組件里調(diào)用 beforeRouteUpdate
- 調(diào)用路由獨(dú)享守衛(wèi) beforeEnter。
- 解析異步路由組件。
- 在將要進(jìn)入的路由組件中調(diào)用 beforeRouteEnter
- 調(diào)用全局解析守衛(wèi) beforeResolve
- 導(dǎo)航被確認(rèn)。
- 調(diào)用全局后置鉤子的 afterEach 鉤子。
- 觸發(fā)DOM更新(mounted)。
- 執(zhí)行beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)
觸發(fā)鉤子的完整順序
路由導(dǎo)航、keep-alive、和組件生命周期鉤子結(jié)合起來(lái)的,觸發(fā)順序,假設(shè)是從a組件離開,第一次進(jìn)入b組件∶
- beforeRouteLeave:路由組件的組件離開路由前鉤子,可取消路由離開。
- beforeEach:路由全局前置守衛(wèi),可用于登錄驗(yàn)證、全局路由loading等。
- beforeEnter:路由獨(dú)享守衛(wèi)
- beforeRouteEnter:路由組件的組件進(jìn)入路由前鉤子。
- beforeResolve:路由全局解析守衛(wèi)
- afterEach:路由全局后置鉤子
- beforeCreate:組件生命周期,不能訪問tAis。
- created;組件生命周期,可以訪問tAis,不能訪問dom。
- beforeMount:組件生命周期
- deactivated:離開緩存組件a,或者觸發(fā)a的beforeDestroy和destroyed組件銷毀鉤子。
- mounted:訪問/操作dom。
- activated:進(jìn)入緩存組件,進(jìn)入a的嵌套子組件(如果有的話)。
- 執(zhí)行beforeRouteEnter回調(diào)函數(shù)next。
導(dǎo)航行為被觸發(fā)到導(dǎo)航完成的整個(gè)過(guò)程
- 導(dǎo)航行為被觸發(fā),此時(shí)導(dǎo)航未被確認(rèn)。
- 在失活的組件里調(diào)用離開守衛(wèi) beforeRouteLeave。
- 調(diào)用全局的 beforeEach守衛(wèi)。
- 在重用的組件里調(diào)用 beforeRouteUpdate 守衛(wèi)(2.2+)。
- 在路由配置里調(diào)用 beforeEnteY。
- 解析異步路由組件(如果有)。
- 在被激活的組件里調(diào)用 beforeRouteEnter。
- 調(diào)用全局的 beforeResolve 守衛(wèi)(2.5+),標(biāo)示解析階段完成。
- 導(dǎo)航被確認(rèn)。
- 調(diào)用全局的 afterEach 鉤子。
- 非重用組件,開始組件實(shí)例的生命周期:beforeCreate&created、beforeMount&mounted
- 觸發(fā) DOM 更新。
- 用創(chuàng)建好的實(shí)例調(diào)用 beforeRouteEnter守衛(wèi)中傳給 next 的回調(diào)函數(shù)。
- 導(dǎo)航完成
9.Vue-router 導(dǎo)航守衛(wèi)有哪些?
- 全局前置/鉤子:beforeEach、beforeResolve、afterEach
- 路由獨(dú)享的守衛(wèi):beforeEnter
- 組件內(nèi)的守衛(wèi):beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
Vue-Router導(dǎo)航守衛(wèi)
在一些場(chǎng)景,比如:最常見的登錄權(quán)限驗(yàn)證,當(dāng)用戶滿足條件時(shí),才讓其進(jìn)入導(dǎo)航;否則就取消跳轉(zhuǎn),并跳到登錄頁(yè)面讓其登錄。
為此有很多種方法可以植入路由的導(dǎo)航過(guò)程:
- 全局的
- 單個(gè)路由獨(dú)享的
- 組件級(jí)的
全局路由鉤子
vue-router全局有三個(gè)路由鉤子;
- router.beforeEach 全局前置守衛(wèi),進(jìn)入路由之前
- router.beforeResolve 全局解析守衛(wèi)(2.5.0+),在 beforeRouteEnter 調(diào)用之后調(diào)用
- router.afterEach 全局后置鉤子,進(jìn)入路由之后
具體使用∶
- beforeEach(判斷是否登錄了,沒登錄就跳轉(zhuǎn)到登錄頁(yè))
- afterEach (跳轉(zhuǎn)之后滾動(dòng)條回到頂部)
router.beforeEach((to, from, next) => {
let ifInfo = Vue.prototype.$common.getSession('userData'); // 判斷是否登錄的存儲(chǔ)信息
if (!ifInfo) {
// sessionStorage里沒有儲(chǔ)存user信息
if (to.path == '/') {
//如果是登錄頁(yè)面路徑,就直接next()
next();
} else {
//不然就跳轉(zhuǎn)到登錄
Message.warning("請(qǐng)重新登錄!");
window.location.href = Vue.prototype.$loginUrl;
}
} else {
return next();
}
});router.afterEach((to, from) => {
// 跳轉(zhuǎn)之后滾動(dòng)條回到頂部
window.scrollTo(0,0);
});單個(gè)路由獨(dú)享鉤子
beforeEnter 如果不想全局配置守衛(wèi)的話,可以為某些路由單獨(dú)配置守衛(wèi),有三個(gè)參數(shù)∶ to、from、next
export default [
{
path: '/',
name: 'login',
component: login,
beforeEnter: (to, from, next) => {
console.log('即將進(jìn)入登錄頁(yè)面')
next()
}
}
]
組件內(nèi)鉤子
beforeRouteUpdate、beforeRouteEnter、beforeRouteLeave這三個(gè)鉤子都有三個(gè)參數(shù)∶to、from、next
- beforeRouteEnter∶ 進(jìn)入組件前觸發(fā)
- beforeRouteUpdate∶ 當(dāng)前地址改變并且改組件被復(fù)用時(shí)觸發(fā),舉例來(lái)說(shuō),帶有動(dòng)態(tài)參數(shù)的路徑foo/∶id,在 /foo/1 和 /foo/2 之間跳轉(zhuǎn)的時(shí)候,由于會(huì)渲染同樣的foa組件,這個(gè)鉤子在這種情況下就會(huì)被調(diào)用
- beforeRouteLeave∶ 離開組件被調(diào)用
注意點(diǎn),beforeRouteEnter組件內(nèi)還訪問不到this,因?yàn)樵撌匦l(wèi)執(zhí)行前組件實(shí)例還沒有被創(chuàng)建,需要傳一個(gè)回調(diào)給 next來(lái)訪問,例如:
beforeRouteEnter(to, from, next) {
next(target => {
if (from.path == '/classProcess') {
target.isFromProcess = true
}
})
}10.Vue-router跳轉(zhuǎn)和location.href有什么區(qū)別?
- 使用location.href= /url 來(lái)跳轉(zhuǎn),簡(jiǎn)單方便,但是刷新了頁(yè)面;
- 使用history.pushState( /url ) ,無(wú)刷新頁(yè)面,靜態(tài)跳轉(zhuǎn);
- 引進(jìn) router ,然后使用router.push( /url )來(lái)跳轉(zhuǎn),使用了 diff 算法,實(shí)現(xiàn)了按需加載,減少了 dom 的消耗。
- 其實(shí)使用 router 跳轉(zhuǎn)和使用history.pushState()沒什么差別的,因?yàn)関ue-router就是用了history.pushState() ,尤其是在history模式下。
參考文章
https://juejin.cn/post/6964779204462247950
https://mp.weixin.qq.com/s/7TLVBK2A73-1f7yOPMWMHg
網(wǎng)頁(yè)名稱:一文搞定常考Vue-Router知識(shí)點(diǎn)
分享網(wǎng)址:http://fisionsoft.com.cn/article/cddpejg.html


咨詢
建站咨詢
