路由是什麼
在網路原理中,路由指的是分組從源到目的地時,決定端到端路徑的網路範圍的程式,做成硬體叫路由器,在路由器中維護著一個路由表,並根據此路由表決定下一跳的地址。在 web 中,一樣的原理,是指根據不同的 url 給其分配不同的控制器(處理程式)。
前端路由的出現
在最初的 web 開發中,我們並不太關注到路由,這和當時的開發方式有關,是後端模板的渲染方式,我們常看到的 jsp,php 都是這種方案,由後端根據請求資訊來決定顯示什麼樣的頁面,此時路由是在服務端配置的。這時候的路由就是 url 和後端伺服器的互動,根據不同的路徑顯示不同的資源,頁面也是一種資源。這種開發方式有明顯的不足,每切換一個頁面都要重新載入一次,即使兩個頁面有很多相同的地方。還有就是前後端的程式碼揉雜在一起,前端要部署一個既有前端程式碼又有後端程式碼的專案,不方便本地開發除錯,一旦後端程式碼有錯誤,前端無法進行開發,前端被限制在後端的開發方式中,效率很低,前端迫切的需要一種革新來改變這種開發方式。
隨著前後端分離和 MVVM 概念的興起及前端工程化的發展,出現了一種新的開發方式,SPA 單頁應用,前端圈迅速崛起,有了爆發式的發展。單頁應用的意思是隻有一個頁面,是無重新整理的,看到的頁面之間的跳轉其實只是元件的切換,同時 URL 也要相應的變化,為了實現這種單頁應用,出現了前端路由。
前端路由到底是什麼
那麼前端路由到底是什麼?用一句話說就是 URL 和元件樹的對映關係。因為單頁應用前端整個工程實際上只有一個頁面,不同的 url 只是在切換不同的元件,實際上就是監聽 url 的變化然後按照他的規則來進行匹配。
前端路由的實現
前端路由的實現方式主要有兩種:
- hash
- history
1、hash 即 window.loacation.hash,url 中以“#”為識別符號,如:www.xxx/com/list.ht… ,這個值可讀可寫,讀取時,可以用來判斷網頁狀態,寫入時會在不重新載入網頁的情況下給瀏覽器增加一條歷史記錄,有了這種特性就有了前端路由的雛形,因為改變#之後的內容相當於改變了 url,但是並沒有重新向伺服器傳送請求。JavaScript 可以通過 window.onhashchange 來監聽 url 變化,以實現不同元件的切換。
目前主要的路由庫有 vue-router,react-router,他們的主要功能是儲存路由的 hash 以及對應的函式,然後監聽 hash 的變化執行對應的函式。以 vue-router 為例,看一下他的監聽原始碼:
setupListeners () { //設定監聽器
const router = this.router
const expectScroll = router.options.scrollBehavior
const supportsScroll = supportsPushState && expectScroll
if (supportsScroll) {
setupScroll()
}
window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {
const current = this.current
if (!ensureSlash()) {
return
}
this.transitionTo(getHash(), route => {
if (supportsScroll) {
handleScroll(this.router, route, current, true)
}
if (!supportsPushState) { // hash變化改變view
replaceHash(route.fullPath)
}
})
})
}
複製程式碼
這裡他把 hashchange 是作為降級方案處理的,因為有更優的處理方式,下面會講。這裡只是設定監聽的程式碼,當然他的前後還有一些“鉤子”,即跳轉前,跳轉後要執行的方法,甚至有可能取消此次跳轉。
2、由於 html5 的釋出,引入了 history.pushState()
和 history.replaceState()
方法,它們分別可以新增和修改歷史記錄條目。pushState 需要三個引數,一個狀態物件(可以通過 onpopstate 事件獲取到),一個標題 (目前被忽略)和一個 URL,replaceState 引數也是一樣。通常與 window.onpopstate
配合使用,這個為前端路由的另一種模式奠定了基礎,但是這種方式的 url 是一個完整的如http://www.xxx.com/list/complete
,他每一次改變都會向服務傳送一次請求資源(其實我們是沒有這個頁面地址的),所以需要伺服器端增加一條配置,如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是我們的主頁面。
下面我們用此種方法做一個簡版的路由,開發思想涉及到了觀察者模式,都是考慮最簡單的情況。
結尾
目前 web 路由整體思路上是一樣的,將 url 對映到元件,在加上一系列的複雜情況的處理,比如說 hash 模式和 history 模式如何相容,重定向,別名,巢狀,傳參,然後是跳轉,路由之間的跳轉需要提供各種“鉤子”,處理好各種情況就是一個完整的前端路由庫了。