這篇文章帶給大家的內容是關於前端路由的實現方式及其基本原理的介紹(附示例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。
一. 前端路由
現代前端開發中最受歡迎的頁面模型,莫過於SPA單頁應用架構。單一頁面應用程式指的是應用程式只有一個主頁,透過動態取代DOM內容並同步修改url位址,來模擬多頁應用程式的效果,切換頁面的功能直接由前台腳本來完成,而不是由後端渲染完畢後前端只負責顯示。前端三駕馬車Angular,Vue,React皆基於此模型來運行的。 SPA能夠以模擬多頁面應用的效果,歸功於其前端路由機制。
前端路由,顧名思義就是一個前端不同頁面的狀態管理器,可以不向後台發送請求而直接透過前端技術實現多個頁面的效果。 angularjs中的ui-router,vue中的vue-router,以及react的react-router皆是對此功能的具體實作。
既然前端路由
這麼屌,那必須的好好研究一下。
二. 兩種實作方式及其原理
常見的路由插件中兩種方式都是支援且可以切換的,例如angularjs1.x中就可以透過以下程式碼從Hash模式切換到H5模式:
$locationProvider.html5Mode(true);
切換到HTML5的路由模式,主要用於避免url位址中包含#而引發的問題。
1.HashChange
1.1 原理
HTML頁面中透過錨點定位原理可進行無刷新跳轉,觸發後url位址中會多出#
'XXX'的部分,同時在全域的window物件上觸發hashChange事件,這樣在頁面錨點哈希改變為某個預設值的時候,透過程式碼觸發對應的頁面DOM改變,就可以實現基本的路由了,基於錨點哈希的路由比較直觀,也是一般前端路由插件中最常用的方式。
1.2 應用
下面透過一個實例看一下,當點擊angularjs的連接時,可以看到控制台列印出了對應的資訊。
2.HTML5 HistoryAPI
2.1 原理
HTML5的History API為瀏覽器的全域history物件增加的擴充方法。一般用來解決ajax請求無法透過回退按鈕回到請求前狀態的問題。
在HTML4中,已經支援window.history物件來控制頁面歷史記錄跳轉,常用的方法包括:
history.forward(); //在歷史記錄中前進一步
history.back(); //在歷史記錄中後退一步
#history.go(n): //在歷史記錄中跳到n步驟,n=0為刷新本頁,n=-1為後退一頁。
在HTML5中,window.history
物件得到了擴展,新增的API包括:
# #history.pushState(data[,title][,url]);//向歷史記錄中追加一筆記錄
history.replaceState(data[, title][,url]);//取代目前頁在歷史記錄中的資訊。
history.state;//是一個屬性,可以得到目前頁面的state資訊。
window.onpopstate;//是一個事件,在點擊瀏覽器後退按鈕或js呼叫forward()、back()、go()時觸發。監聽函數中可傳入一個event對象,event.state即為透過pushState()或replaceState()方法傳入的data參數。
2.2 應用程式
瀏覽器存取一個頁面時,目前位址的狀態資訊會被壓入歷史堆疊,當呼叫history.pushState()方法向歷史棧中壓入新的state後,歷史堆疊頂端的指標是指向新的state的。可以將其作用簡單理解為假裝已經修改了url地址並進行了跳轉,除非用戶點擊了瀏覽器的前進,回退,或是顯式調用HTML4中的操作歷史棧的方法,否則不會觸發全局的popstate事件。
在下面的範例中,點擊導航按鈕,可以看到url網址列發生了變化,且控制台列印出了回應的資訊。
3.hash 與history API比較
##對比
#url字串
|
|
|
#命名限制
通常只能在同一個 | document下進行改變 url位址可以自己定義,只要是同一個域名下都可以,自由度更大 |
|
url位址變更
會改變 |
可以改變,也可以不改變 |
|
#狀態儲存
無內建方法,需要另行儲存頁面的狀態資訊 |
#將頁面資訊壓入歷史堆疊時可以附帶自訂的資訊 |
|
參數傳遞能力
受到url總長度的限制, |
將頁面資訊壓入歷史堆疊時可以附帶自訂的資訊 |
|
實用性
可直接使用 |
通常服務端需要修改程式碼以配合實作 |
| ##相容性
#IE8以上 | IE10以上 |
| #三.親手造一個簡單的前端路由插件
造輪子,不是為了把它裝在你的車上,而是當你在荒郊野外開車而輪子出了問題時多一種選擇。
接下來就自己動手實作一個前端路由的外掛程式~
3.1基於Hash的前端路由外掛程式myHashRouter.js
我們希望實現的功能是:
1.引入MyHashRouter.js庫
2.透過when()方法定義若干不同的路由狀態
3.透過init()方法啟動路由功能
4.透過點擊導航實現前端路由切換
首先編寫js骨架,如圖所示:
;(function() {
function Router() {
//记录路由的跳转历史
this.historyStack = [];
//记录已注册的路由信息
this.registeredRouter = [];
//路由匹配失败时跳转项
this.otherwiseRouter = {
path: '/',
content: 'home page'
}
}
/*
* 启动路由功能
*/
Router.prototype.init = function() {
}
/*
* 绑定window.onhashchange事件的回调函数
*/
Router.prototype._bindEvents = function() {
}
/**
* 路由注册方法
*/
Router.prototype.when = function(path, content) {
}
/**
* 判断新添加的路由是否已存在
*/
Router.prototype._hasThisRouter = function(path) {
}
/**
* 路由不存在时的指定地址
*/
Router.prototype.otherwise = function(path, content) {
}
/**
* 路由跳转方法,主动调用时可用于跳转路由
*/
Router.prototype.go = function(topath) {
}
/**
* 用于将对应路由信息渲染至页面,实现路由切换
*/
Router.prototype.render = function (content) {
}
var router = new Router();
//将接口暴露至全局
window.$router = router;
})();
完成了路由插件的編寫後,我們在demo中引入該函式庫,然後使用when()
方法註冊幾個路由位址,再使用init()
方法啟動路由,腳本部分程式碼如下:
效果:
運行附件中的router-demo-hash.html
,點擊導航按鈕,即可看到url網址列以及內容區域同步變更。
3.2基於History API的前端路由外掛程式myHistoryRouter.js
由於History API不支援低於IE10以下版本的瀏覽器(其他大多數現代瀏覽器基本上都支援),所以我們在init()方法啟動時先進行可用性判斷,基本程式碼框架與基於Hash的路由插件一致。每個方法的實作不難寫,這裡不再贅述,筆者自己的程式碼實作放在附件myHashRouter.js中,等級有限,僅供參考。
3.3整合說明
為方便理解,本例中將兩種模式分開編寫,如果是外掛程式庫的開發,可以模仿 ui-router增加一個html5mode()
的方法,在init()
方法啟動路由時,根據所傳的參數產生不同的路由插件的單例,也就是我們常說的工廠模式來實現即可。
四.後記
造車輪
是一個很好的學習方式,雖然自己造的車輪很簡陋,但是對於理解工具的底層原理卻很有幫助。
本例只是編寫了一個路由工具的基本骨架,真正的路由工具還需要做很多功能擴展,個別功能的複雜度也會很高,例如路徑的正則匹配,懶加載,組合視圖,嵌套視圖,路由動畫等等,有興趣的小夥伴可以在本例提供的框架上進行學習擴展。
#
以上是前端路由的實作方式及其基本原理的介紹(附範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!