在學習完vue.js以及vuex之后,我們還剩下vue全家桶中的最后一個需要學習的組件,這就是vue-router了,本篇文章我們就來一起認識和入門vue-router。為什么我們只是入門呢?因為在這里我不會把官方文檔中的每一個細節都講的清清楚楚,如果需要精通,仍然需要多多閱讀官方文檔和自我實踐。
1.vue-router是什么?
它是一個vue.js下的路由組件。
2.路由是什么?
router,即“路由”。路由是一個網絡工程里面的術語。James F.Kurose,Keith W.Ross著.陳鳴譯.《計算機網絡》中有講到
路由(routing)是指分組從源到目的地時,決定端到端路徑的網絡范圍的進程
在WEB開發的世界里面,路由其實指的就是控制我們在瀏覽器中輸入的URL應該走入哪個頁面中的一個組件。
3.為什么需要路由?
在最原始的ASP,以及傳統的 開發中,我們在瀏覽器路徑中輸入URL,位於服務器上的WEB服務器程序(比如說Apache httpd)則會自動更加這URL,找到WEB目錄下對應的文件,通過一些解析器將服務端腳本執行之后返回的HTML內容發回給瀏覽器,瀏覽器將收到的HTML渲染出來。這時WEB服務器程序(比如說Apache httpd)自己就完成了這個路由功能。
比如說wordpress的后台就是
http://www.changwei.me/wp-admin/post-new.php
直接請求對應的php腳本,該腳本執行之后返回HTML給瀏覽器渲染。
但是現在越來越流行框架開發了,很多PHP項目都是用框架開發的,框架都遵循單一入口原則,也就是在WEB目錄下只有一個index.php文件和一些靜態資源文件,其他所有業務邏輯以及框架本身的代碼都寫在WEB目錄外面的各種文件中,所有入站請求都到達入口文件,入口文件再通過請求的各種參數來判斷應該是將請求分發給WEB目錄外的哪個文件(控制器)執行。我們如果有幸能夠找到一些使用非常老的PHP框架開發的網站,觀察他們的站內連接,各種URL上面有可能會像這種樣子
http://xxx.com/index.php?module=home&controller=passport&action=login
等等,這就是該框架通過入口文件接受module,controller,action等參數來判斷究竟應該把該請求分發給哪個模塊,哪個控制器,哪個操作去處理。這樣就可以十分神奇的實現只有一個文件就處理千千萬萬邏輯的方法。
到了現在WEB2.0時代,信息分享是很多用戶上網的主要操作,如果你的URL足夠簡短美觀,那么用戶只需要簡單的輸入URL就可以訪問對應的網頁,而不用輸入一堆module,controller,action之類的非IT行業的用戶看起來不明不白的單詞。同時也為了SEO(搜索引擎優化)和URL美觀,因此路由便誕生了。
路由可以進一步將類似於
http://xxx.com/index.php?module=home&controller=passport&action=login
這樣的URL簡寫成
http://xxx.com/login
這樣看起來是不是美觀了很多。
4.Apache自帶URL重寫可以達到上述目的,為什么還需要路由?
如果你會問出這個問題,你一定還沒有體驗過PHP的Laravel框架。
我們看一看Laravel在輸出hello world的時候,用xphrof做性能測試的結果,發現路由相關的操作占據了大量執行時間,從中也可以側面看出Laravel中路由的功能強大。
前面說了這么多,還是沒講到路由究竟好在哪?為什么不用各種WEB服務器自帶的URL重寫功能?
首先URL重寫只是單純的正則表達式匹配請求URL,然后將請求轉發到真正的URL路徑上執行,這里從高內聚低耦合的角度來看,URL重寫將一個WEB程序的業務邏輯分散到了WEB服務器程序和WEB程序兩個地方。並且我們從Apache服務器程序換到nginx上還需要修改配置文件,移植性降低了。另外我們有的時候需要對一組URL進行一些特殊的操作,比如說所有后台操作請求都必須驗證登錄操作,在傳統的開發中,要么在每一個后台操作的腳本(控制器)中寫一個驗證操作,更加高級一點的會include一個驗證腳本,但是怎么看還是不夠優雅。現在有路由了,可以將一組和后台操作有關的URL都划分到一個分組中,然后綁定中間件(和java中的過濾器,攔截器很像)
5.vue-router在前端開發中能帶來什么好處?
前面講了這么多關於路由的好處,其實都指的是后端路由。也就是前后端不分離的項目中的路由。現在我們是前后端分離項目中,路由有什么用,能帶來什么好處呢?
我們先看看知乎客戶端
這是知乎客戶端的兩個頁面。
我們先來看看這個需求:
有一天產品經理說需要開發一個像知乎一樣的SPA,要求底部有一些按鈕固定不動的底部導航欄,頂部也有一個帶有返回按鈕的導航欄固定不動,點擊底部導航欄之后,中間部分的頁面應該跳轉到對應功能頁面,點擊頂部的返回按鈕之后,應該返回到之前的頁面。
如果是傳統開發,你肯定第一想到的是使用css的display進行切換顯示不同的vue組件(components)實現。
但是我們看到知乎底部的“我的”按鈕存在一個邏輯,如果用戶沒有登錄,那么他會跳轉到登錄頁面,如果已經登錄則顯示對應頁面。如果使用傳統開發,那么就會顯得很不優雅。
另外還要考慮一個情況,就是一般訪問SPA的用戶都是移動端,移動端最需要考慮的就是加載速度,並且不能耗費用戶過多流量。那么就需要讓用戶點擊這個按鈕之后再加載這個組件的相關代碼,以及該組件需要請求的數據,最后在渲染頁面。
最后就是URL要美觀漂亮,並且URL可以動態接受參數,比如說網易雲音樂這個非常典型的SPA項目便使用了后端路由並且可以接受參數
http://music.163.com/#/my/m/music/playlist?id=121597667
要滿足這些需求的話,在vue.js下使用vue-router是最合適不過的了。
6.vue-router都提供了什么?
1.前端路由(編程式導航 · GitBook):讓頁面中的部分內容可以無刷新的跳轉,就像原生APP一樣。
2.懶加載(懶加載 · GitBook):結合異步組件以及在組建的created鈎子上觸發獲取數據的ajax請求(數據獲取 · GitBook)可以最大化的降低加載時間,減少流量消耗。
3.重定向(重定向 和 別名 · GitBook):可以實現某些需要根據特定邏輯改變頁面原本路由的需求,比如說未登錄狀態下訪問“個人信息”時應該重定向到登錄頁面。
4.美化URL(HTML5 History 模式):還記得前面網易雲音樂的URL嗎?
http://music.163.com/#/my/m/music/playlist?id=121597667
網易雲音樂網頁版的URL里面幾乎都帶有一個#號,大家可能會疑惑,#號是URL的hash部分,並不會傳遞到服務端,那么#號起什么作用呢?其實前端路由器就是通過URL的hash部分來像傳統的后端路由器一樣判斷某些請求需要交給哪個前端組件處理。
但是大家都會覺得URL里面帶一個#號太丑了,要是能像傳統WEB應用一樣的URL多好。這個時候vue-router提供的“HTML5 History 模式”就“完美”解決了這個問題。
為什么前面的完美要加上引號呢?
請參考官方文檔:
不過這種模式要玩好,還需要后台配置支持。因為我們的應用是個單頁客戶端應用,如果后台沒有正確的配置,當用戶在瀏覽器直接訪問 http://oursite.com/user/id 就會返回 404,這就不好看了。
所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個index.html 頁面,這個頁面就是你 app 依賴的頁面。
這里還要引出另一個話題,就是為什么前端路由的時候需要改變URL呢?前面提到了WEB2.0時代是一個信息分享的時代,如果用戶切換到了另一個頁面,但是URL仍然顯示的是index.html,那么用戶想要分享這個頁面給他的朋友,他的朋友訪問到的則只是這個SPA的首頁,並不是這個分享的用戶本身希望他朋友看到的頁面。因此前端路由在改變頁面的時候必須讓URL跟着一起變。這樣同時也近似完美地解決了歷史上ajax導致瀏覽器返回前進按鈕失效的問題。
5.前置操作,中間件,過濾器,攔截器(導航鈎子 · GitBook)
在后端路由中都有前置操作,中間件,過濾器,攔截器等概念。前端路由也可以有的,vue-router本身較為完美的支持了這些功能,讓你做前端SPA開發就像后端開發一樣。在第三點提到的用戶未登錄重定向的判斷邏輯就可以寫在這里。
6.路由元信息(路由元信息 · GitBook):后端路由中可以對路由規則進行分組,比如說把所有需要登錄才能訪問的頁面划分為一組。vue-router並沒有路由規則分組功能,但是它提供了路由元信息,可以在元信息中定義一些規則,在路由鈎子中再去判斷這些規則,進行相應的操作。
7.滾動位置控制(滾動行為 · GitBook):相對於官方翻譯的滾動行為,我更喜歡自己將他翻譯為“滾動位置控制”,官方文檔對於它的作用已經講的比較通俗易懂了,大家可以參閱官方文檔學習。
總結:
有了vue-router之后,你的前端SPA項目才更像一個能夠真正投入生產環境,用戶體驗良好的項目。結合Vue.js+Webpack全家桶,可以讓你的前端開發效率以及項目的用戶體驗更上一層樓。如果需要對vue-router有更多了解,歡迎閱讀官方文檔:Introduction · GitBook