前言
Vue-Router提出來是為了解決什么問題歌逢,跟以前寫<a>標(biāo)簽或者重新打開一個(gè)瀏覽器窗口有什么不同誉尖,有什么優(yōu)勢揭鳞,它的實(shí)現(xiàn)原理是什么等等帶著這些問題我們來深入了解一下Vue-Router。
背景
以前我們打開頁面一般都是用<a>標(biāo)簽或location.herf或window.open等方式靴拱,我們發(fā)現(xiàn)有時(shí)候每打開一個(gè)頁面都會有點(diǎn)卡褥芒,因?yàn)槲覀兠看蜷_一個(gè)瀏覽器窗口都會重新加載所需要的資源包括公共css嚼松、js、圖片等等锰扶,很多頁面都加載的是同樣的公共資源献酗,這樣子就會造成瀏覽器性能的大量消耗,并且前端重復(fù)的代碼非常多坷牛,因?yàn)榇a不能復(fù)用罕偎,比如頭部或者底部很多html文件都要寫一份,很不利于維護(hù)京闰,特別是遇到復(fù)雜項(xiàng)目的時(shí)候颜及,工作量成倍增加。為了注重用戶體驗(yàn)(降低瀏覽器性能損耗)蹂楣、開發(fā)大型復(fù)雜的項(xiàng)目(組件化俏站,不需要重復(fù)寫大量的代碼)這兩個(gè)主要難題的時(shí)候,單頁面應(yīng)用被提了出來痊土。
單頁面應(yīng)用(SPA)
單頁面應(yīng)用是指只有一個(gè)頁面的應(yīng)用肄扎,在瀏覽器中運(yùn)行期間不會重新加載頁面,之后所有的交互操作都在一個(gè)頁面上完成赁酝,這些都是通過vue-router切換不同的vue組件來顯示不同的組件內(nèi)容反浓。公共資源(js、css等)僅需加載一次且一次全部加載赞哗,所以會有首屏問題雷则,就是第一次打開頁面有點(diǎn)慢,多頁面應(yīng)用是按需加載公共資源肪笋,所以沒有首屏問題月劈。
如圖:
從上圖我們可以看到Page-One度迂、Page-Two、Page-Three共用一個(gè)Header和Footer猜揪。
多頁面應(yīng)用(MPA)
多頁面跳轉(zhuǎn)重新加載頁面惭墓,所需公共資源(js、css等)會重新加載而姐,所以很多頁面都會加載相同的公共資源腊凶,造成瀏覽器性能的巨大浪費(fèi)。
如圖:
從上圖我們可以看到Page-One拴念、Page-Two钧萍、Page-Three每個(gè)頁面都需要分別寫一個(gè)Header和Footer造成大量代碼重復(fù)。
具體對比分析:
單頁面應(yīng)用 | 多頁面應(yīng)用 | |
---|---|---|
組成 | 一個(gè)index.html頁面和若干組件組成 | 多個(gè)完整頁面構(gòu)成 |
資源共用(css政鼠、js风瘦、img等) | 共用,只需要在index.html頁面加載 | 不共用公般,每個(gè)頁面都需要加載 |
刷新方式 | 頁面局部刷新或更改 | 整頁刷新 |
url模式 | a.com/#/pageone a.com/#/pagetwo | a.com/pageone.html a.com/pagetwo.html |
用戶體驗(yàn) | 頁面組件的切換快万搔,用戶體驗(yàn)好 | 頁面之間的切換加載緩慢,流暢度不夠官帘,用戶體驗(yàn)比較差 |
轉(zhuǎn)場動畫 | 容易實(shí)現(xiàn) | 無法實(shí)現(xiàn) |
數(shù)據(jù)傳遞 | 容易 | 依賴url傳參瞬雹、cookie、localStorage等 |
搜索引擎優(yōu)化(SEO) | 需要單獨(dú)方案刽虹、實(shí)現(xiàn)較為困難挖炬、不利于SEO檢索,可利用服務(wù)器端渲染(SSR)優(yōu)化 | 實(shí)現(xiàn)方法簡易 |
試用范圍 | 高要求的體驗(yàn)度状婶、追求界面流暢的應(yīng)用 | 適用于追求高度支持搜索引擎的應(yīng)用 |
開發(fā)成本 | 較高意敛,常需借助專業(yè)的框架 | 較低,但頁面重復(fù)代碼多 |
維護(hù)成本 | 相對容易 | 相對復(fù)雜 |
從上圖我們可以看到單頁面應(yīng)用的優(yōu)勢和劣勢:
單頁面應(yīng)用的好處
- 用戶體驗(yàn)好膛虫,快草姻,內(nèi)容的改變不需要重新加載整個(gè)頁面,基于這一點(diǎn)SPA對服務(wù)器壓力較小稍刀。從性能和用戶體驗(yàn)的層面來比較的話撩独,后端路由每次訪問一個(gè)新頁面的時(shí)候都要向服務(wù)器發(fā)送請求,然后服務(wù)器再響應(yīng)請求账月,這個(gè)過程肯定會有延遲综膀。而前端路由在訪問一個(gè)新頁面的時(shí)候僅僅是變換了一下路徑而已,沒有了網(wǎng)絡(luò)延遲局齿,對于用戶體驗(yàn)來說會有相當(dāng)大的提升剧劝。
- 單頁面應(yīng)用沒有頁面之間的切換,就不會出現(xiàn)"白屏現(xiàn)象"抓歼,也不會出現(xiàn)假死并有"閃爍"現(xiàn)象讥此。
- 良好的前后端分離拢锹。后端不再負(fù)責(zé)模版渲染、輸出頁面工作萄喳,只需要出數(shù)據(jù)就可以卒稳,后端API通用化,即同一套后端程序代碼他巨,不用修改就可以用于web界面充坑、手機(jī)、平板等客戶端染突。
單頁面應(yīng)用的缺點(diǎn)
- 首次加載耗時(shí)比較多:為實(shí)現(xiàn)單頁Web應(yīng)用功能及顯示效果捻爷,需要在第一次打開頁面的時(shí)候?qū)⑺泄操Y源JavaScript、CSS觉痛、圖片等一起加載役衡,所以會有首屏問題茵休,就是第一次打開頁面有點(diǎn)慢薪棒。
- SEO難度較高:搜索引擎爬蟲工具只會爬取到后端返回的html內(nèi)容(不支持ajax數(shù)據(jù)的爬取也就是不能爬取接口返回的數(shù)據(jù)),單頁面應(yīng)用只會在第一次進(jìn)入頁面的時(shí)候會向后端請求html文件榕莺,這時(shí)候會被搜索引擎爬蟲工具檢索到俐芯,但是在切換組件的時(shí)候是不需要向后端發(fā)送請求html文件的,所以是無法被爬蟲工具檢索到的钉鸯,多頁面應(yīng)用每次頁面跳轉(zhuǎn)后端服務(wù)器都會返回一個(gè)新的html文檔吧史,會被爬蟲工具檢索到唠雕。
針對以上兩個(gè)缺點(diǎn)vue又提出了SSR來解決贸营。
Vue-Router原理
這里的路由是SPA的路徑管理器。Vue-Router是Vue.js官方的路由插件岩睁,它和Vue.js是深度集成的钞脂,適合于構(gòu)建單頁面應(yīng)用。Vue的單頁面應(yīng)用是基于路由和組件的捕儒,路由用于設(shè)定訪問路徑冰啃,并將路徑和組件映射起來。傳統(tǒng)的頁面刘莹,是通過超鏈接來實(shí)現(xiàn)頁面跳轉(zhuǎn)阎毅,在Vue-Router單頁面應(yīng)用中,則是路徑之間的切換点弯,也就是組件的切換扇调。Vue路由的本質(zhì)就是建立起hash路由和組件之間的映射關(guān)系。
單頁面應(yīng)用的核心之一是更新視圖而不重新請求頁面抢肛,Vue-Router在實(shí)現(xiàn)單頁面應(yīng)用前端路由時(shí)肃拜,提供了兩種方式:Hash模式和History模式痴腌,根據(jù)mode參數(shù)來決定采用哪一種方式,這兩種方式都不會讓頁面重新加載燃领。
Hash模式:
我們經(jīng)常在url中看到#士聪,這個(gè)#有兩種作用,一種用來實(shí)現(xiàn)錨點(diǎn)功能猛蔽,一種用來做hash路由剥悟,hash是#號后面的部分,單單改變#后的部分是不會刷新頁面曼库,不會重新加載頁面区岗,同時(shí)每一次改變#后的部分,都會在瀏覽器的訪問歷史中增加一條記錄毁枯,使用后退按鈕就可以回到上一個(gè)頁面慈缔,Vue-Router就是利用這一點(diǎn)來實(shí)現(xiàn)前端路由。主要原理是通過監(jiān)聽 # 后的 URL 路徑標(biāo)識符的更改而觸發(fā)的瀏覽器 的hashchange 事件种玛,然后通過獲取 location.hash 得到當(dāng)前的路徑標(biāo)識符藐鹤,再進(jìn)行一些路由跳轉(zhuǎn)的操作。
History模式
由于hash模式會在url中自帶#赂韵,如果不想要很丑的 hash娱节,我們可以用路由的 history 模式,只需要在配置路由規(guī)則時(shí)祭示,加入"mode: 'history'"肄满,這種模式充分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法。這兩個(gè)方法應(yīng)用于瀏覽器記錄棧质涛,在當(dāng)前已有的 back稠歉、forward、go 基礎(chǔ)之上汇陆,它們提供了對歷史記錄修改的功能怒炸。只是當(dāng)它們執(zhí)行修改時(shí),雖然改變了當(dāng)前的 URL 瞬测,但瀏覽器不會立即向后端發(fā)送請求横媚。
//main.js文件中
const router = new VueRouter({
mode: 'history',
routes: [...]
})
當(dāng)你使用 history 模式時(shí),URL 就像正常的 url月趟,如 http://yoursite.com/user/id灯蝴,看上去就像修改了url。不過這種模式要玩好孝宗,還需要后臺配置支持穷躁。因?yàn)槲覀兊膽?yīng)用是個(gè)單頁客戶端應(yīng)用,如果后臺沒有正確的配置,當(dāng)用戶在瀏覽器直接訪問 http://oursite.com/user/id就會返回 404问潭,這就不好看了猿诸。所以呢,你要在服務(wù)端增加一個(gè)覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源狡忙,則應(yīng)該返回同一個(gè) index.html 頁面梳虽,這個(gè)頁面就是你 app 依賴的頁面。
export const routes = [
{path: "/", name: "homeLink", component:Home}
{path: "/register", name: "registerLink", component: Register},
{path: "/login", name: "loginLink", component: Login},
{path: "*", redirect: "/"}]
此處就設(shè)置如果URL輸入錯(cuò)誤或者是URL 匹配不到任何靜態(tài)資源灾茁,就自動跳到到Home頁面窜觉。
文檔和API總結(jié)
參考文章:
路由源碼:https://juejin.im/post/5cd8d609e51d456e7b372155
https://mp.weixin.qq.com/s/xVDUtqA-V3jXO_-orFDfCg/#/32434324