前端路由學習總結

本文總結自:

最初接觸前端路由是vue-router,當時僅僅覺得可以通過router-link改變頁面,覺得很神奇呀,用多了就習慣了。

后面接觸了node,通過express知曉了后端路由,這是我就開始疑問了:
為什么使用那些前端框架的時候,前端url改變了視圖,但是卻沒有向后臺發送請求?

首先我們需要一些前置知識。

路由/前端路由/后端路由?

路由:通過不同的url地址展示不同的內容或者頁面。

前面提到過,我最初接觸到路由是通過express框架,我們先看一段代碼:

app.post('/category/add', function (req, res, next) {
   // do something
})

如果你沒有接觸過node也沒關系,因為真的不難理解。

定義了一個path('/categoty/add'),當有人通過(即域名+path),例如:

http://www.example.com/category/add

發起post請求時,就會進入后臺定義好的回調函數,進行邏輯處理,譬如取得post傳遞過來的實體數據,對數據庫進行增刪查改,然后返回一個渲染好的html頁面或者是json數據等等。

后端路由(不考慮提供API服務返回數據),這一過程由服務器控制完成的,直接噴射一個html給前端,瀏覽器頁面刷新。

那前端路由是什么呢?還是通過不同的url地址展示不同的內容或者頁面,但是這一過程都是由前端完成的,我們的頁面或視圖(模塊)是在前端編寫好,通過url變化去切換而已。

為什么需要前端路由:

因為后臺每次返回一個新頁面都會進行全局刷新,而在單頁面應用中,大部分頁面結構不變,只改變部分內容的使用,我們可以通過前端路由改變頁面內容,后臺只需要通過ajax提供數據即可。

現在,我們來看看前端路由到底是如何實現的。

實現簡易前端路由

首先我們需要了解HTML5為我們提供的history API,準確的說是這里面的兩個方法:
history.pushState和history.replaceState

history.pushState

帶有三個參數:一個狀態對象,一個標題(現在被忽略了),以及一個可選的URL地址。下面將對這三個參數進行細致的檢查:

實例代碼(來自Web開發中 前端路由 實現的幾種方式和適用場景

//假設當前網頁URL為:http://tonylee.pw
window.history.pushState(null, null, "http://tonylee.pw?name=tonylee");
//url變化:http://tonylee.pw -> http://tonylee.pw?name=tonylee

window.history.pushState(null, null, "http://tonylee.pw/name/tonylee");
//url變化:http://tonylee.pw -> http://tonylee.pw/name/tonylee

window.history.pushState(null, null, "?name=tonylee");
//url變化:http://tonylee.pw -> http://tonylee.pw?name=tonylee

window.history.pushState(null, null, "name=tonylee");
//url變化:http://tonylee.pw -> http://tonylee.pw/name=tonylee

window.history.pushState(null, null, "/name/tonylee");
//url變化:http://tonylee.pw -> http://tonylee.pw/name/tonylee

window.history.pushState(null, null, "name/tonylee");
//url變化:http://tonylee.pw -> http://tonylee.pw/name/tonylee

//錯誤的用法:
window.history.pushState(null, null, "http://www.tonylee.pw?name=tonylee");
//error: 由于跨域將產生錯誤

history.replaceState

pushState()和replaceState()參數一樣。
兩個方法的主要區別就是:pushState()是在history棧中添加一個新的條目,replaceState()是替換當前的記錄值。關于API的詳細解釋可以戳這里

我們需要知道的是,就是兩個方法可以改變瀏覽器的url,但是不會重新加載頁面,沒錯!!!這些 URL 不會直接傳給服務器,而是會被瀏覽器消化處理掉.

這個就是我們需要的。

這樣我們就可以通過這兩個方法改變url了。

改變之后呢?切換視圖呀!

那我們就需要在這兩個方法被調用的時候,觸發一個方法去切換視圖,好在HTML5也給我們提供了一個事件。

window.onpopstate

瀏覽器本身會自帶一個popstate事件,但是只有在我們點擊返回或前進按鈕時才會正常觸發。

很顯然,在我們單頁應用中是需要你去大部分情況下都是需要去點擊某個Link調用pushState,而這樣是無法觸發popstate事件的,需要重寫一下pushState,并且給他也定義一個事件,這里就叫他onpushstate吧,比如下面這樣。

(function(history){
    var pushState = history.pushState;    
    history.pushState = function(state) {
        if (typeof history.onpushstate == "function") {            
            history.onpushstate({state: state});        
        }
        return pushState.apply(history, arguments);   
    }
})(window.history)

window.onpopstate = history.onpushstate = function(event) {
    // change view
}

如此一來,進行pushState操作會觸發onpushstate事件,我們可以在onpushstate事件的回調中進行視圖切換了,而前進后退我們可以通過popstate來操作。

別忘了給a標簽做一些必要操作,阻止默認跳轉,而是通過pushState改變url,然后由于pushState被調用,又會觸發onpushstate事件,其內的邏輯代碼就會被執行,比如,切換視圖。

var elements = document.getElementsByTagName('a');
for(var i = 0, len = elements.length; i < len; i++) {    
    elements[i].onclick = function (event) {        
        event.preventDefault();
        var route = event.target.getAttribute('href');        
        history.pushState({page: route}, route, route)
    }
}

前端路由的基本實現就是以上了,代碼來自余博倫-知乎首頁,現在再回頭看vue-router/react-router是否清晰了一點呢,當然其內部實現遠遠不是這么簡單。

小知識-pjax

pjax是一種基于ajax+history.pushState的新技術,該技術可以無刷新改變頁面的內容,并且可以改變頁面的URL。pjax是ajax+pushState的封裝,同時支持本地存儲、動畫等多種功能。目前支持jquery、qwrap、kissy等多種版本。

眾所周知,Ajax可以實現頁面的無刷新操作——優點;但是,也會造成另外的問題,無法前進與后退!曾幾何時,Gmail似乎借助iframe搞定,如今,HTML5讓事情變得如同過家家般簡單。

當執行Ajax操作的時候,往瀏覽器history中塞入一個地址(使用pushState)(這是無刷新的);于是,返回的時候,通過URL或其他傳參,我們就可以還原到Ajax之前的模樣。

ajax與HTML5 history pushState/replaceState實例-張鑫旭

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一. Backbone的江湖地位: backbone作為一個老牌js框架為大規模前端開發提供了新的開發思路:前端M...
    Michael_bdb5閱讀 1,091評論 0 4
  • 什么是前端路由路由,引導、指路之意。 譬如我們熟知的路由器,蹦跶在網絡層的數據包轉發設備,在網絡中也是扮演著指路明...
    藍淺藍深閱讀 777評論 0 5
  • 原文鏈接:https://github.com/halfrost/Halfrost-Field/blob/mast...
    hament閱讀 5,702評論 1 31
  • 原文見martin的博客 最近一直在研究前后端分離,ajax可以很好的解決前后端分離的問題,但是又存在著瀏覽器無法...
    small_a閱讀 9,687評論 4 34
  • 小時候,家里建房子,建房子的那塊地在同村惡霸家旁。此惡霸有六七個兒子,個個蠻橫無理,欺良霸市,方圓幾百里無...
    掌心書閱讀 325評論 1 1