一、什么是前端路由
在web開發的過程中,路由的使用是必不可少的,這里的路由不是指我們日常生活中的路由器,但是實現原理基本相同,它代表一個url與相應處理程序的影射關系,用戶在輸入要訪問的url之后,路由會解析url中的路徑,之后根據映射表中的映射關系查找相應的預設函數,並將結果返回給用戶,以此完成一次操作。
前端路由不同於傳統路由,它不需要服務器來進行解析,而是通過一個hash函數或者H5提供的history API來實現。在進行開發時,路由用來設定訪問路徑,並將路徑與相應的組件映射起來,用戶在訪問相應的路徑時,路由根據映射關系實現不同組件間的切換,整個過程都是在同一個頁面中實現,不涉及頁面間的跳轉,也就是我們常說的單頁應用。
二、前端路由的優勢
1、頁面刷新速度快。由於后端路由在請求一個新路徑時,會重新向服務器發送請求,之后再根據服務器的相應結果重新渲染頁面,這個過程會受到網絡延遲的影響,而前端路由省略了整個請求過程,只是完成部分組件間的切換,因此頁面的刷新速度會相對較快,用戶體驗相對較好。
2、復用性強。使用前端路由,代碼中的layout、css、js都可以共用,以此來減少重復加載,提供程序性能。
3、頁面狀態可記錄。不使用前端路由,僅通過ajax進行頁面局部切換的單頁應用,由於url始終保持不變,因此頁面的狀態是無法記錄的,而前端路由很好的解決了這個問題。例如使用了前端路由的url:http://music.taihe.com/fe/a這個鏈接,再打開后會直接觸發/a的事件。
三、前端路由的實現方法
目前前端路由的實現方法主要有兩種方法,location.hash和window.history。
1、通過location.hash實現前端路由
hash就是一個url中#后面的部分,也叫做url的錨部分,錨部分在服務器端會被自動忽略,但是在瀏覽器中是可以通過loaction.hash來獲取的。通過hash方法實現前端路由主要是用到的是onhashchange事件,這個事件可以實時監聽url中hash值的變化,由此來根據hash值的變化進行一些DOM的切換操作。
onhashchange的語法如下:
HTML中:
<element onhashchange="myScript">
Javascipt中:
object.onhashchange=function(){myScript};
Javascript中,使用addEventListener()方法:
object.addEventListener("hashchange", myScript);
onhashchange事件有如下幾種觸發條件:
a)改變url地址,在最后面增加或改變其hash值;
b)改變location.href或location.hash的值;
c)點擊帶有錨點的鏈接;
d)瀏覽器前進后退可能導致hash的變化,前提是兩個網頁地址中的hash值不同。
利用Hash實現前端路由:
設計思路:當瀏覽器地址欄url的hash值發生變化時,就會觸發onhashchange事件,這時通過window.location.hash可以拿到當前瀏覽器的url的hash值,注意此時的hash值是帶有#的,因此需要對其值進行相應的處理,去掉#,並且如果當前url不含hash值的話,就將其當做根目錄處理。之后將url和相應的組件函數進行映射,根據不同的hash值執行不同的回調函數,也就是加載相應的組件。
代碼如下:




這里簡單寫了一個DOM元素,用來模擬路由接受到url后對不同組件的切換情況
此時,點擊不同a標簽可以實現組件間的切換,同時,頁面並沒有刷新。
2、通過window.history和popstate實現前端路由
瀏覽器窗口會為用戶提供一個history對象,用來保存用戶操作頁面的歷史,我們在瀏覽網頁時的前進后退操作都是基於這個對象來實現的。
在前端路由的實現過程中主要用到了history對象里的history.pushState()和history.replaceState()這兩個接口。
history.replaceState(dataObj,title,url);
history.pushState(dataObj,title,url);
pushState()和replaceState()方法很類似,二者均接受三個參數,分別是state、title和url。
其中state用來存放將要插入的history實體的相關信息,它是一個json格式的參數;
title就是傳入history實體的標題,需要注意的是firefox現在會自動忽略掉這個參數;
url用來傳遞新的history實體的相對路徑,如果其值為null則表示當前要插入的history實體與前一個實體一致,沒有改變。
replaceState()方法與pushState()方法的唯一區別在於,replaceState()方法會將最新一條的history實體覆蓋掉,而不是直接添加,這種情況在處理例如登錄頁面這些不需要記錄到history中的情況時非常有用。
這里需要注意的是history提供的這兩個方法不會主動出發瀏覽器頁面的刷新,只是history對象包括地址欄的內容會發生改變,當出發前進后退等history事件時才會進行相應的響應。
另外,作為參數傳入的url也會受到同源策略的限制,如果出現跨域等情況會導致報錯。
popstate是官方提供的事件,當我們執行刷新或點擊操作時才會觸發該事件。
利用history實現前端路由:
設計思路:當想要跳轉到指定url的時候,將目標url通過pushState()或者replaceState()方法填入到history和地址欄中,此時由於上述兩種方法不會主動進行頁面刷新,因此頁面仍停留在當前頁面,只是url地址發生了改變。之后通過popstate事件響應,執行相應的回調函數,實現前端組件間的切換。
這里直接使用mozilla的例子,代碼如下:


可以看到在點擊相應的dom元素的時候地址欄和相應的router-view同時發生了改變。
總結:
前端路由由於其刷新速度快、用戶體驗好的特點在web開發中已經被廣泛的使用了,許多大型的前端框架,如react、vue都有自己的前端路由,關於前端路由的學習不能僅停留在會使用上,更應該從底層原理入手學習。今后還會對vue-router、react-router等源碼進行學習,從而使自己能夠對前端路由有更細致深刻的了解和解讀。