history和hash詳解

1、historycss

window.history(可直接寫成history)指向History對象,它表示當前窗口的瀏覽歷史。
History對象保存了當前窗口訪問過的全部頁面網址html

1. length前端

history.length屬性保存着歷史記錄的url數量,初始時該值爲1,若是當前窗口前後訪問了三個網址,那麼history對象就包括3項,history.length=3

2.跳轉方法:容許在瀏覽器歷史之間移動vue

go()  接受一個整數爲參數,移動到該整數指定的頁面,好比history.go(1)至關於history.forward(),history.go(-1)至關於history.back(),history.go(0)至關於刷新當前頁面
back()  移動到上一個訪問頁面,等同於瀏覽器的後退鍵,常見的返回上一頁就能夠用back(),是從瀏覽器緩存中加載,而不是從新要求服務器發送新的網頁
forward()  移動到下一個訪問頁面,等同於瀏覽器的前進鍵

若是移動的位置超出了訪問歷史的邊界,以上三個方法並不報錯,而是默默的失敗

3.history.pushState()html5

在瀏覽器歷史中添加記錄vue-router

if(!!(window.hostory && history.pushState)) {
    // 支持History API
} else {
    // 不支持
}

以上代碼能夠用來檢查當前瀏覽器是否支持History API。若是不支持的話能夠考慮使用Polyfill庫History.js

history.pushstate()方法接受三個參數,以此爲:後端

state: 一個與指定網址相關的狀態對象,popState事件觸發時,該對象會傳入回調函數,若是不須要這個對象,此處可填null
title: 新頁面的標題,可是全部瀏覽器目前都忽略這個值,所以這裏能夠填null
url: 新的網址,必須與當前頁面處在同一個域,瀏覽器的地址欄將顯示這個網址

假定當前網址是example.com/1.html,咱們使用pushState方法在瀏覽記錄(history對象)中添加一個記錄跨域

var stateObj = {foo:'bar'};
history.pushState(stateObj,'page 2','2.html')

添加上邊這個新紀錄後,瀏覽器地址欄馬上顯示example.com/2.html,但不會跳轉到2.html,甚至也不會檢查2.html是否存在,它只是成爲瀏覽歷史中的新紀錄。這時,你在地址欄輸入一個新的地址,而後點擊了後退按鈕,頁面的url將顯示2.html;你再點擊以此後退按鈕,url將顯示1.html
總之,pushState方法不會觸發頁面刷新,只是致使了history對象發生變化,地址欄會有反應。
若是pushState的url參數,設置了一個新的錨點值(即hash),並不會觸發hashChange事件,若是設置了一個跨域網址,則會報錯。瀏覽器

//報錯
history.pushState(null,null,'https://twitter.com/hello')

上邊代碼中,pushState()想要插入一個跨域的網址,致使報錯,這樣設計的目的是防止惡意代碼讓用戶覺得他們是在另外一個網站上緩存

4. history.replaceState()
history.replaceState()方法的參數和pushState()方法一摸同樣,區別是它修改瀏覽器歷史當中的記錄
假定當前頁面是example.com/example.html

history.pushState({page:1},'title 1','?page=1')
history.pushState({page:2},'title 2','?page=2')
history.replaceState({page:3},'title 3','?page=3')

history.back() //url顯示爲example.com/example.html?page=1
history.back() //url顯示爲example.com/example.html
history.go(2) //url顯示爲example.com/example.html?page=3

5. history.state屬性
history.state返回當前頁面的state對象

history.pushState({page:1},'title 1','?page=1')
history.state  //{page:1}

5. popState 事件
每當同一個文檔的瀏覽歷史(即history)出現變化時,就會觸發popState事件
須要注意:僅僅調用pushState方法或replaceState方法,並不會觸發該事件,只有用戶點擊瀏覽器後退和前進按鈕時,或者使用js調用back、forward、go方法時纔會觸發。另外該事件只針對同一個文檔,若是瀏覽歷史的切換,致使加載不一樣的文檔,該事件不會被觸發
使用的時候,能夠爲popState事件指定回調函數

window.onpopstate = function (event) {
  console.log('location: ' + document.location);
  console.log('state: ' +JSON.stringify(event.state));
};

// 或者

window.addEventListener('popstate', function(event) {
  console.log('location: ' + document.location);
  console.log('state: ' + JSON.stringify(event.state));
});

回調函數的參數是一個event事件對象,它的state屬性指向pushState和replaceState方法爲當前url所提供的狀態對象(即這兩個方法的第一個參數)。上邊代碼中的event.state就是經過pushState和replaceState方法爲當前url綁定的state對象
這個state也能夠直接經過history對象讀取
history.state
注意:頁面第一次加載的時候,瀏覽器不會觸發popState事件

6.history.scrollRestoration

history.scrollRestoration = 'manual';關閉瀏覽器自動滾動行爲
history.scrollRestoration = 'auto';打開瀏覽器自動滾動行爲(默認)

2、hash
hash 就是指 url 尾巴後的 # 號以及後面的字符。這裏的 # 和 css 裏的 # 是一個意思。hash 也 稱做 錨點,自己是用來作頁面定位的,她可使對應 id 的元素顯示在可視區域內。

經過window.location.hash獲取hash值

延伸:
window.location對象裏面
hash  : 設置或返回從 (#) 開始的 URL(錨)。
host  : 設置或返回主機名和當前 URL 的端口號。
hostname:設置或返回當前 URL 的主機名。
href : 設置或返回完整的 URL。
pathname: 設置或返回當前 URL 的路徑部分。
port:設置或返回當前 URL 的端口號。
search : 設置或返回從問號 (?) 開始的 URL(查詢部分)。
assign() : 加載新的文檔。
reload() : 從新加載當前文檔。
replace() : 用新的文檔替換當前文檔。

hash主要是一個事件:hashchange,當hash值改變時會觸發這個事件
語法:window.onhashchange = fun
或者:<body onhashchange="fun">
以上事件將覆蓋現有的事件處理程序,爲了添加一個新的事件處理程序,而不覆蓋已有的其餘的事件處理程序,可使用函數"addEventListener"

window.addEventListener('hashchange',fun,false)

例子:

if('onhashchange' in window) {
   alert("該瀏覽器支持 hashchange 事件!");
}
function locationHashChanged() {
    if (location.hash === "#somecoolfeature") {
        somecoolfeature();
    }
}
window.onhashchange = locationHashChanged;

hashchange事件有兩個屬性:

newURL: string類型,當前頁面新的url
oldURL: string類型,當前頁面舊的url


window.addEventListener('hashchange', function (e) {
  console.log(e.newURL,e.oldURL)
  var str = e.newURL.split('#')[1]
  document.getElementById('num').innerHTML = str.split('=')[1]
})

3、vue-router中history和hash兩種模式的區別

在vue的路由配置中有mode選項 最直觀的區別就是在url中hash帶了一個很醜的#,而history是沒有#的

mode:"hash",
mode:"history"

hash和history模式的不一樣👇
對於vue這類漸進式的前端開發框架,爲了構建spa單頁面應用,須要引入前端路由系統,也就是vue-router存在的意義。前端路由的核心就在於---改變視圖的同時不會向後端發出請求。
爲了達到這一目的,瀏覽器提供瞭如下兩種支持:

  • hash-----即地址欄url中的#符號,好比:http://www.baidu.com/#/a,hash...。它的特色在於#/a雖然在url中,但不會被包括在http請求中,對後端徹底沒有影響,所以改變hash不會從新加載頁面。
  • history-----利用了html5 History Interface中新增的pushState()和replaceState()方法。這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的back、forward、go的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改時,雖然改變了當前的url,但瀏覽器不會當即向後端發送請求。
  • 所以能夠說,hash模式和history模式都屬於瀏覽器自身的特性,vue-router只是利用了這兩個特性(經過瀏覽器提供的接口)來實現前端路由。

使用場景:
通常場景下,hash和history均可以,除非你更在乎顏值,#符號夾雜在url裏看起來確實不太美麗。
若是不想要很醜的hash,咱們能夠用路由的history模式,這種模式充分利用history.pushState API來完成url跳轉而無需從新加載頁面。
另外,調用history.pushState()相比於直接修改hash,存在如下優點:

  • pushState()設置的新的url能夠是於當前url同源的任意url,而hash只可修改#後面的部分,所以只能設置與當親url同文檔的url
  • pushState()設置的新的url能夠與當前url一摸同樣,這樣也會把記錄添加到棧中;而hash設置的新值必須與原來的不同纔會觸發動做將記錄添加到棧中
  • pushState()經過stateObject參數能夠添加任意類型的數據到記錄中;而hash只可添加短字符串
  • pushState()可額外設置title屬性提供後續使用

clipboard.png

固然啦,history也不是樣樣都好,spa雖然在瀏覽器裏遊刃有餘,但真要經過url向後端發起請求時,差別就來了,尤爲在用戶手動輸入url後回車,或者刷新(重啓)瀏覽器的時候,會報一個404的錯誤,找不到指定路由,須要後端去指向正確的路由匹配, 好比當url不匹配時跳轉到index.html.

若是Vue後臺部署使用的是Nginx, 能夠這樣配置

location / {
   try_files $uri $uri/ /index.html;#支持history模式刷新
   root   /www/test/hello/;
   index   index.html;
}
相關文章
相關標籤/搜索