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

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


咨詢
建站咨詢
