路由的基礎理解【轉】

定義:路由是用來把請求映射到路由處理程序。應用程序一啓動就配置了路由,而且能夠從URL中提取值用於處理請求。它還負責使用 ASP.NET 應用程序中定義的路由來生成連接。javascript

 

路由使用 routes 類 ( iRouter 的實現) 作到:html

  • 映射傳入的請求到 路由處理程序
  • 生成響應中使用的 URLs

 

1. 服務器端路由

對於服務器來講,當接收到客戶端發來的HTTP請求,會根據請求的URL,來找到相應的映射函數,而後執行該函數,並將函數的返回值發送給客戶端。對於最簡單的靜態資源服務器,能夠認爲,全部URL的映射函數就是一個文件讀取操做。對於動態資源,映射函數多是一個數據庫讀取操做,也多是進行一些數據的處理,等等。java

以Express爲例,數據庫

app.get('/', (req, res) => { res.sendFile('index') }) app.get('/users', (req, res) => { db.queryAllUsers() .then(data => res.send(data)) }) 

這裏定義了兩條路由:api

  • 當訪問/的時候,會返回index頁面
  • 當訪問/users的時候,會從數據庫中取出全部用戶數據並返回

不單單是URL瀏覽器

在router匹配route的過程當中,不只會根據URL來匹配,還會根據請求的方法來看是否匹配。例如上面的例子,若是經過POST方法來訪問/users,就會找不到正確的路由。ruby

2. 客戶端路由

對於客戶端(一般爲瀏覽器)來講,路由的映射函數一般是進行一些DOM的顯示和隱藏操做。這樣,當訪問不一樣的路徑的時候,會顯示不一樣的頁面組件。客戶端路由最多見的有如下兩種實現方案:服務器

  • 基於Hash
  • 基於History API

(1) 基於Hash

咱們知道,URL中#及其後面的部分爲hash。例如:app

const url = require('url') var a = url.parse('http://example.com/a/b/#/foo/bar') console.log(a.hash) // => #/foo/bar 

hash僅僅是客戶端的一個狀態,也就是說,當向服務器發請求的時候,hash部分並不會發過去。asp.net

經過監聽window對象的hashChange事件,能夠實現簡單的路由。例如:

window.onhashchange = function() { var hash = window.location.hash var path = hash.substring(1) switch (path) { case '/': showHome() break case '/users': showUsersList() break default: show404NotFound() } } 

(2) 基於History API

經過HTML5 History API能夠在不刷新頁面的狀況下,直接改變當前URL。詳細用法能夠參考:

Manipulating the browser history
Using the HTML5 History API
咱們能夠經過監聽window對象的popstate事件,來實現簡單的路由:

window.onpopstate = function() { var path = window.location.pathname switch (path) { case '/': showHome() break case '/users': showUsersList() break default: show404NotFound() } } 

可是這種方法只能捕獲前進或後退事件,沒法捕獲pushState和replaceState,一種最簡單的解決方法是替換pushState方法,例如:

var pushState = history.pushState history.pushState = function() { pushState.apply(history, arguments) // emit a event or just run a callback emitEventOrRunCallback() } 

不過,最好的方法仍是使用實現好的history庫。

(3) 兩種實現的比較

總的來講,基於Hash的路由,兼容性更好;基於History API的路由,更加直觀和正式。

可是,有一點很大的區別是,基於Hash的路由不須要對服務器作改動,基於History API的路由須要對服務器作一些改造。下面來詳細分析。

假設服務器只有以下文件(script.js被index.html所引用):

/-
 |- index.html |- script.js 

基於Hash的路徑有:

http://example.com/ http://example.com/#/foobar 

基於History API的路徑有:

http://example.com/ http://example.com/foobar 

當直接訪問http://example.com/的時候,二者的行爲是一致的,都是返回了index.html文件。

當從http://example.com/跳轉到http://example.com/#/foobar或者http://example.com/foobar的時候,也都是正常的,由於此時已經加載了頁面以及腳本文件,因此路由跳轉正常。

當直接訪問http://example.com/#/foobar的時候,實際上向服務器發起的請求是http://example.com/,所以會首先加載頁面及腳本文件,接下來腳本執行路由跳轉,一切正常。

當直接訪問http://example.com/foobar的時候,實際上向服務器發起的請求也是http://example.com/foobar,然而服務器端只能匹配/而沒法匹配/foobar,所以會出現404錯誤。

所以若是使用了基於History API的路由,須要改造服務器端,使得訪問/foobar的時候也能返回index.html文件,這樣當瀏覽器加載了頁面及腳本以後,就能進行路由跳轉了。

相關文章
相關標籤/搜索