還記得jquery時代嗎,那時前端三大框架還沒流行,前端開發者瘋狂查着jquery的API文檔來進行dom操做,還記得這個地址嗎 jquery.cuishifeng.cn/ 是否是頗有感受!(想了解前端歷史的,請看我這篇文章前端技術發展 juejin.im/post/5cc6b5…javascript
記得在學校裏剛開始寫網頁的時候,只是對JavaScript學了個大概,而後就開始學jquery進行網頁開發了。css
若是你曾經也是jquery開發者,看到這塊代碼時,杯中的水開始顫抖,啊!個人青春啊!html
那時畢業後的大半年寫前端就只用了 jquery ,沒有如今這些前端框架提供的工程化,模塊化,組件化(其實有,但我還沒學沒用,並且我進的第一個公司那時我是公司的第一個前端,沒有前輩的教導,本身摸索)。寫前端就用了js(jquery),css,html,來進行項目的工程文件目錄結構搭建。想一想那段日子可真累啊!前端
那時寫網頁時遇到個需求:java
假設一個頁面左側是若干導航連接,右側是內容,同時導航時只有右側的內容須要更新,那麼刷新整個頁面無疑是浪費的(本來每一個導航連接都是a標籤href跳轉網頁)。這時咱們可使用 AJAX 來拉取右面的數據。可是若是僅僅這樣,地址欄是不會改變的,用戶沒法前進、後退,也沒法收藏當前頁面或者把當前頁面分享給他人;搜索引擎抓取也有困難。jquery
這時,查到 HTML5 的 History API 就能夠解決這個問題。web
思路:數據庫
首先綁定click事件。當用戶點擊一個連接時,經過preventDefault函數防止默認的行爲(頁面跳轉),同時讀取連接的地址(若是有jQuery,能夠寫成 $(this).attr('href')),把這個地址經過pushState塞入瀏覽器歷史記錄中,再利用 AJAX 技術拉取(若是有 jQuery,可使用$.get方法)
這個地址中真正的內容,同時替換當前網頁的內容。後端
爲了處理用戶前進、後退,咱們監聽popstate事件。當用戶點擊前進或後退按鈕時,瀏覽器地址自動被轉換成相應的地址,同時popstate事件發生。在事件處理函數中,咱們根據當前的地址抓取相應的內容,而後利用 AJAX 拉取這個地址的真正內容,呈現,便可。設計模式
最後,整個過程是不會改變頁面標題的,能夠經過直接對document.title賦值來更改頁面標題。
代碼相似於這樣:
window.history.pushState(null, null, "/profile/");
複製代碼
這套 API 提供一種「人爲操縱」瀏覽器歷史記錄的方法。
瀏覽器歷史記錄能夠看做一個「棧」。棧是一種後進先出的結構,能夠把它想象成一摞盤子,用戶每點開一個新網頁,都會在上面加一個新盤子,叫「入棧」。用戶每次點擊「後退」按鈕都會取走最上面的那個盤子,叫作「出棧」。而每次瀏覽器顯示的天然是最頂端的盤子的內容。
var state = {
id: 2,
name: "profile"
};
window.history.pushState(state, "My Profile", "/profile/");
// 它能夠接收三個參數,按順序分別爲:
// 1.一個對象或者字符串,用於描述新記錄的一些特性。這個參數會被一併添加到歷史記錄中,以供之後使用。這個參數是開發者根據本身的須要自由給出的。
// 2.一個字符串,表明新頁面的標題。當前基本上全部瀏覽器都會忽略這個參數。
// 3.一個字符串,表明新頁面的相對地址。
複製代碼
當用戶點擊瀏覽器的「前進」、「後退」按鈕時,就會觸發popstate事件。你能夠監聽這一事件,從而做出反應。
window.addEventListener("popstate", function(e) {
var state = e.state;
// do something...
});
// 這裏e.state就是當初pushState時傳入的第一個參數。例如,在咱們的例子中,有:
// e.state.id == 2;
// e.state.name == "profile";
複製代碼
有時,你但願不添加一個新記錄,而是替換當前的記錄(好比對網站的 landing page),則可使用replaceState方法。這個方法和pushState的參數徹底同樣。
hash也是一種改變瀏覽器url而不會刷新頁面的方案
「#」表明網頁中的一個位置。其右面的字符,就是該位置的標識符
瀏覽器讀取這個URL後,會自動滾動至comment評論位置區域。
爲網頁位置指定標識符,有兩個方法。
<a name="comment"></a>
複製代碼
<div id="comment"></div>
複製代碼
因此當咱們使用的時候不指定標識符,網頁就不會定位,但又能獲得咱們想要的改變瀏覽器url而不會刷新頁面
‘#’是用來指導瀏覽器動做的,對服務器端徹底無用。因此,HTTP請求中不包括#。
好比,訪問下面的網址, juejin.im/post/5dc664… 咱們打開F12查看network的all,看第一條,咱們發現並無#comment這部分數據傳參
history是瀏覽器的歷史記錄,location是瀏覽器當前url信息(hash就是其中的值),他們都是瀏覽器BOM提供的api
這是一個HTML 5新增的事件,當#值發生變化時,就會觸發這個事件。
function hashHandler() {
console.log('The hash has changed!');
}
window.addEventListener('hashchange', hashHandler, false);
複製代碼
這塊內容都是找的網上的文章,網上資料不少,學習了兩篇 juejin.im/post/5d469f… juejin.im/post/5d2d19…
路由的概念起源於服務端,在之前先後端不分離的時候,由後端來控制路由,當接收到客戶端發來的 HTTP 請求,就會根據所請求的相應 URL,來找到相應的映射函數,而後執行該函數,並將函數的返回值發送給客戶端。對於最簡單的靜態資源服務器,能夠認爲,全部 URL 的映射函數就是一個文件讀取操做。對於動態資源,映射函數多是一個數據庫讀取操做,也多是進行一些數據的處理等等。而後根據這些讀取的數據,在服務器端就使用相應的模板來對頁面進行渲染後,再返回渲染完畢的頁面。它的好處與缺點很是明顯:
也正是因爲後端路由還存在着本身的不足,前端路由纔有了本身的發展空間。對於前端路由來講,路由的映射函數一般是進行一些 DOM 的顯示和隱藏操做。這樣,當訪問不一樣的路徑的時候,會顯示不一樣的頁面組件。
SPA 是 single page web application 的簡稱,譯爲單頁Web應用。
簡單的說 SPA 就是一個WEB項目只有一個 HTML 頁面,一旦頁面加載完成,SPA 不會由於用戶的操做而進行頁面的從新加載或跳轉。 取而代之的是利用 JS 動態的變換 HTML 的內容,從而來模擬多個視圖間跳轉。
前端路由不是什麼新技術,咱們只是使用了後端使用的路由這個名稱,其實他就是對瀏覽器的hash模型和history模式的封裝(各個前端框架都封裝了各自的路由,咱們查閱文檔按照規則規範使用就行)。
因此當咱們知道瀏覽器的hash和history後就能明白一些以前咱們以爲神奇的地方。
咱們不造輪子,但咱們得知道這個輪子出來的目的及意義,基於什麼原理。若是你對這個輪子很感興趣,那你能夠閱讀源碼,學習裏面的代碼思路,設計模式,但不要鑑於已有的東西再造一個,沒有意義。
若是你想了解一些路由的簡單封裝,點擊前面貼出的兩篇文章地址,學習一下。深刻學習請看三大框架路由源碼,自行摸索。