從代碼分析,從頭構(gòu)建一個(gè)vue項(xiàng)目需要理解vue的各個(gè)知識(shí)點(diǎn)惫搏。
當(dāng)你使用npm創(chuàng)建一個(gè)vue項(xiàng)目之后具温,首先接觸的就是app.vue。該文件的內(nèi)容也很簡(jiǎn)單晶府,最開(kāi)始就是如下:
從這里就可以看到<router-view/>
而這個(gè)就是大名鼎鼎的前端路由桂躏,可以知道,凡是整個(gè)項(xiàng)目都是DOM直出的頁(yè)面川陆,我們都稱它為“傳統(tǒng)頁(yè)面”(SSR 屬于首屏直出剂习,這里我不認(rèn)為是傳統(tǒng)頁(yè)面的范疇)。那么什么是DOM直出呢较沪?
簡(jiǎn)單說(shuō)就是在瀏覽器輸入網(wǎng)址后發(fā)起請(qǐng)求鳞绕,返回來(lái)的HTML頁(yè)面是最終呈現(xiàn)的效果尸曼,那就是DOM直出。并且每次點(diǎn)擊頁(yè)面跳轉(zhuǎn)冤竹,都會(huì)重新請(qǐng)求HTML資源鹦蠕。
說(shuō)的更簡(jiǎn)單一點(diǎn)就是你去查看一些網(wǎng)頁(yè)開(kāi)發(fā)者模式钟病,查看以下network請(qǐng)求返回的的資源 如果是頁(yè)面資源除了css跟script文件以外 全部都有刚梭,那么就是傳統(tǒng)的DOM直出朴读。
而隨著對(duì)網(wǎng)頁(yè)需求的不斷增高,網(wǎng)頁(yè)也越來(lái)越傾向轉(zhuǎn)為模塊化缘回、組件化的道路。而順勢(shì)而生的React啦吧、?Vue拙寡、?Angular?等著名單頁(yè)面應(yīng)用框架肆糕。而這些框架有一個(gè)共同的特點(diǎn),便是“通過(guò) JS 渲染頁(yè)面”淮摔。
這些單頁(yè)面框架之后和橙,?HTML頁(yè)面基本上只有一個(gè)?DOM?入口造垛,大致如下所示:
所有的頁(yè)面組件办斑,都是通過(guò)運(yùn)行上圖底部的?app.js腳本杆逗,掛載到?<div id="root"></div>?這個(gè)節(jié)點(diǎn)下面罪郊。用一個(gè)極其簡(jiǎn)單的 JS 展示掛載這一個(gè)步驟:
既然單頁(yè)面是這樣渲染的排龄,那如果我有十幾個(gè)頁(yè)面要互相跳轉(zhuǎn)切換橄维,咋整U琛3鹤啤店溢?床牧?這時(shí)候?前端路由?應(yīng)運(yùn)而生戈咳,它的出現(xiàn)就是為了解決單頁(yè)面網(wǎng)站著蛙,通過(guò)切換瀏覽器地址路徑耳贬,來(lái)匹配相對(duì)應(yīng)的頁(yè)面組件咒劲。
簡(jiǎn)單來(lái)說(shuō)下邏輯就是:
http://192.168.12.216:8080/#/中國(guó)---->定位到? /中國(guó) ----->跳轉(zhuǎn)到中國(guó)這個(gè)組件
http://192.168.12.216:8080/#/美國(guó)---->定位到? /美國(guó)----->跳轉(zhuǎn)到美國(guó)?這個(gè)組件
前端路由?會(huì)根據(jù)瀏覽器地址欄 pathname?的變化缎患,去匹配相應(yīng)的頁(yè)面組件挤渔。然后將其通過(guò)創(chuàng)建 DOM?節(jié)點(diǎn)的形式,塞入根節(jié)點(diǎn) <div id="root"></div>?嫉父。這就達(dá)到了無(wú)刷新頁(yè)面切換的效果眼刃,從側(cè)面也能說(shuō)明正因?yàn)闊o(wú)刷新擂红,所以 React?、 Vue?树碱、 Angular?等現(xiàn)代框架在創(chuàng)建頁(yè)面組件的時(shí)候成榜,每個(gè)組件都有自己的 生命周期?赎婚。
這里終于說(shuō)到我們的Vue-Router
為了讓大家對(duì)前端路由的原理有一個(gè)更深刻的理解,我們來(lái)通過(guò)分析哈希模式和歷史模式的實(shí)現(xiàn)原理來(lái)幫助大家明白前端路由是怎么實(shí)現(xiàn)的纬凤。
哈希模式
a標(biāo)簽錨點(diǎn)大家應(yīng)該不陌生移斩,而瀏覽器地址上#后面的變化绢馍,是可以被監(jiān)聽(tīng)的舰涌,瀏覽器為我們提供了原生監(jiān)聽(tīng)事件hashchange瓷耙,它可以監(jiān)聽(tīng)到如下的變化:
點(diǎn)擊a標(biāo)簽搁痛,改變了瀏覽器地址
瀏覽器的前進(jìn)后退行為
通過(guò)window.location方法鸡典,改變?yōu)g覽器地址
歷史模式
history?模式會(huì)比?hash模式稍麻煩一些,因?yàn)?history模式依賴的是原生事件?popstate纽甘,下面是來(lái)自 MDN 的解釋:
需要注意的是調(diào)用history.pushState()/history.replaceState()不會(huì)觸發(fā)popstate事件悍赢。只有在做出瀏覽器動(dòng)作時(shí),才會(huì)觸發(fā)該事件皮胡,如用戶點(diǎn)擊瀏覽器的回退按鈕(javaScript代碼中調(diào)用history.back()/history.forward())
tips:pushState 和 replaceState 都是 HTML5 的新 API,他們的作用很強(qiáng)大瀑梗,可以做到改變?yōu)g覽器地址卻不刷新頁(yè)面。這是實(shí)現(xiàn)改變地址欄卻不刷新頁(yè)面的重要方法谤职。
因?yàn)閍標(biāo)簽點(diǎn)擊事件并不受到popState監(jiān)聽(tīng)亿鲜,所以我們必須想方法組織a標(biāo)簽的默認(rèn)事件蒿柳,加上點(diǎn)擊事件的回調(diào)函數(shù),在回調(diào)函數(shù)內(nèi)獲取?a?標(biāo)簽的?href屬性值妓蛮,再通過(guò)?pushState?去改變?yōu)g覽器的?location.pathname?屬性值蛤克。然后手動(dòng)執(zhí)行?popstate?事件的回調(diào)函數(shù)构挤,去匹配相應(yīng)的路由惕鼓。
以上這段沒(méi)理解也沒(méi)事夫否,因?yàn)楹竺鏁?huì)針對(duì)vue項(xiàng)目中如何絲滑的使用路由進(jìn)行詳解凰慈。