前言:新一季面試季,重新整理一些知識點;
本文詳細說明自己對vue-router原理的理解;
參考:
- 源碼:vuejs/vue-router v2.2.1 - github
- 文檔:vue-router 官方中文教程
- 參考博客 :http://cnodejs.org/topic/58d680c903d476b42d34c72b
VueRouter包括三個主要組成部分 —— VueRouter
、router-view
和 router-link
:
- VueRouter :路由器類,根據路由請求在路由視圖中動態渲染選中的組件
- router-link :路由鏈接組件,聲明用以提交路由請求的用戶接口
- router-view:路由視圖組件,負責動態渲染路由選中的組件
前端路由直接找到與地址匹配的一個組件或者對象然后進行渲染,
實現這一點主要是兩種方式:
1.Hash: 通過改變hash值
2.History: 利用history對象新特性
history
模式需要服務端的配合,而hash
模式不需要
而在vue-router中,它提供mode參數來決定采用哪一種方式,選擇流程如下:
默認Hash-->如果瀏覽器支持History新特性改用History-->如果不在瀏覽器環境則使用abstract
選好mode后創建history對象(HashHistory或HTML5History或AbstractHistory)
可見最被青睞的是History模式,理由是: "#"太丑了。。。
基本方法分析:
Hash
1.push()
功能: 設置新的路由添加歷史記錄並更新視圖,常用情況是直接點擊切換視圖
調用流程:
1 $router.push() //顯式調用方法
2 HashHistory.push() //根據hash模式調用,設置hash並添加到瀏覽器歷史記錄(window.location.hash= XXX)
3 History.transitionTo() //開始更新
4 History.updateRoute() //更新路由
5 {app._route= route}
6 vm.render() //更新視圖
2.replace
功能: 替換當前路由並更新視圖,常用情況是地址欄直接輸入新地址
流程與push基本一致
但流程2變為替換當前hash (window.location.replace= XXX)不懂此方法的可見: http://www.w3school.com.cn/jsref/met_loc_replace.asp
3.監聽地址欄變化
在setupListeners中監聽hash變化(window.onhashchange)並調用replace
History
1.push
與hash模式類似,只是將window.hash改為history.pushState
2.replace
與hash模式類似,只是將window.replace改為history.replaceState
3.監聽地址變化
在HTML5History的構造函數中監聽popState(window.onpopstate)
兩種模式對比
History模式的優點:
1.History模式的地址欄更美觀。。。
2.History模式的pushState、replaceState參數中的新URL可為同源的任意URL(可為不同的html文件),而hash只能是同一文檔
3.History模式的pushState、replaceState參數中的state可為js對象,能攜帶更多數據
4.History模式的pushState、replaceState參數中的title能攜帶字符串數據(當然,部分瀏覽器,例如firefox不支持title,一般title設為null,不建議使用)
缺點:
對於單頁面應用來說,理想的場景是僅僅在進入應用時加載頁面(例如index.html),后續的網絡操作靠ajax完成,
而不會重新請求頁面。
但當用戶直接在用戶欄輸入地址時則會重新請求,當地址帶有參數時兩者情況不一樣
Hash 例如: xxx.com/#/id=5 HTTP請求不會包含后面的hash值,所以請求的仍然是 xxx.com,沒有問題
History 例如: xxx.com/id=5 這時請求的便是xxx.com/id=5,如后端沒有配置對應id=XXX的路由處理,則會返回404錯誤。
官方推薦的解決辦法是在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。同時這么做以后,服務器就不再返回 404 錯誤頁面,因為對於所有路徑都會返回 index.html 文件。為了避免這種情況,在 Vue 應用里面覆蓋所有的路由情況,然后在給出一個 404 頁面。或者,如果是用 Node.js 作后台,可以使用服務端的路由來匹配 URL,當沒有匹配到路由的時候返回 404,從而實現 fallback。