說(shuō)到hash和history的區(qū)別博杖,最直觀的就是在url中闷营,hash帶了#,history沒(méi)有#漠吻,它們兩個(gè)是路由配置mode的兩個(gè)選項(xiàng)。
前端路由的核心是在改變視圖的同時(shí)不會(huì)向后端發(fā)出請(qǐng)求司恳,瀏覽器提供的這兩種支持就是為了達(dá)到這一目的途乃。
1.hash------就是指url中#號(hào)以及后面的字符
①hash也稱作錨點(diǎn),其中的#和css里面的#是一個(gè)意義扔傅,它本身是用來(lái)做頁(yè)面定位的耍共,可以是對(duì)應(yīng)的id元素顯示在可視區(qū)域內(nèi)烫饼。
②我們可以通過(guò)window.location.hash獲取hash值
③hash中有一個(gè)hashchange事件,當(dāng)hash值發(fā)生變化時(shí)會(huì)觸發(fā)這個(gè)事件试读,語(yǔ)法是:window.onhashchange=person? 或者? <body onhashchange='person'>,這個(gè)事件會(huì)覆蓋現(xiàn)有的事件處理程序杠纵,如果在想要添加一個(gè)新的事件處理程序的前提下,還不會(huì)覆蓋原有的事件處理程序钩骇,可以通過(guò)'addEventListener'
window.addEventLister('hashchange',person,false)
另外hashchange事件有兩個(gè)屬性:
newURL: string類(lèi)型比藻,當(dāng)前頁(yè)面新的url
oldURL: string類(lèi)型,當(dāng)前頁(yè)面舊的url
window.addEventListener('hashchange', function (e) { console.log(e.newURL,e.oldURL) })
④地址欄url中的#符號(hào)倘屹,比如:http://www.jd.com/#/a,hash...? ? 它的特點(diǎn)在于#/a雖然在url中银亲,但不會(huì)被包括在http請(qǐng)求中,對(duì)后端完全沒(méi)有影響唐瀑,因此改變hash并不會(huì)導(dǎo)致頁(yè)面的重新加載群凶。
2.history------它直接指向History對(duì)象,它表示當(dāng)前窗口的瀏覽歷史哄辣,History對(duì)象保存了當(dāng)前窗口訪問(wèn)過(guò)的所有頁(yè)面網(wǎng)址
①history.length屬性保存著歷史記錄的url數(shù)量请梢,初始值是 1,如果當(dāng)前窗口訪問(wèn)了四個(gè)網(wǎng)址力穗,那么history.length=4
?②可以在瀏覽器歷史之間移動(dòng)
go()接收一個(gè)整數(shù)為參數(shù)毅弧,移動(dòng)到該整數(shù)指定的頁(yè)面,比如history.go(1)相當(dāng)于history.forward(),history.go(-1)相當(dāng)于history.back(),history.go(0)相當(dāng)于刷新當(dāng)前頁(yè)面
back()移動(dòng)到上一個(gè)訪問(wèn)頁(yè)面当窗,等同于瀏覽器的后退鍵,常見(jiàn)的返回上一頁(yè)就可以用back()够坐,是從瀏覽器緩存中加載,而不是重新要求服務(wù)器發(fā)送新的網(wǎng)頁(yè)
forward()移動(dòng)到下一個(gè)訪問(wèn)頁(yè)面崖面,等同于瀏覽器的前進(jìn)鍵
③history.pushState()------在瀏覽器中添加歷史記錄元咙,這個(gè)方法不會(huì)觸發(fā)頁(yè)面刷新,只是導(dǎo)致了history對(duì)象發(fā)生變化巫员,地址欄會(huì)有反應(yīng)庶香。它有三個(gè)參數(shù):
state: 一個(gè)與指定網(wǎng)址相關(guān)的狀態(tài)對(duì)象,popState事件觸發(fā)時(shí)简识,該對(duì)象會(huì)傳入回調(diào)函數(shù)赶掖,如果不需要這個(gè)對(duì)象,此處可填null
title: 新頁(yè)面的標(biāo)題七扰,但是所有瀏覽器目前都忽略這個(gè)值奢赂,因此這里可以填null
url: 新的網(wǎng)址,必須與當(dāng)前頁(yè)面處在同一個(gè)域颈走,瀏覽器的地址欄將顯示這個(gè)網(wǎng)址
如果pushState的url參數(shù)膳灶,設(shè)置了一個(gè)新的錨點(diǎn)值(即hash),并不會(huì)觸發(fā)hashChange事件立由,如果設(shè)置了一個(gè)跨域網(wǎng)址轧钓,則會(huì)報(bào)錯(cuò)司致。
④history.replaceState()------這個(gè)方法的參數(shù)和pushState()方法一摸一樣,區(qū)別是它修改瀏覽器歷史當(dāng)中的記錄
⑤history.state返回當(dāng)前頁(yè)面的state對(duì)象
⑥每當(dāng)同一個(gè)文檔的瀏覽歷史(即history)出現(xiàn)變化時(shí)聋迎,就會(huì)觸發(fā)popState事件
僅僅調(diào)用pushState方法或replaceState方法,并不會(huì)觸發(fā)該事件枣耀,只有用戶點(diǎn)擊瀏覽器后退和前進(jìn)按鈕時(shí)霉晕,或者使用js調(diào)用back、forward捞奕、go方法時(shí)才會(huì)觸發(fā)牺堰。另外該事件只針對(duì)同一個(gè)文檔,如果瀏覽歷史的切換颅围,導(dǎo)致加載不同的文檔伟葫,該事件不會(huì)被觸發(fā)
使用的時(shí)候,可以為popState事件指定回調(diào)函數(shù)院促,回調(diào)函數(shù)的參數(shù)是一個(gè)event事件對(duì)象筏养,它的state屬性指向pushState和replaceState方法為當(dāng)前url所提供的狀態(tài)對(duì)象(即這兩個(gè)方法的第一個(gè)參數(shù))。
⑦h(yuǎn)istory.scrollRestoration = 'manual';關(guān)閉瀏覽器自動(dòng)滾動(dòng)行為
history.scrollRestoration = 'auto';打開(kāi)瀏覽器自動(dòng)滾動(dòng)行為(默認(rèn))
一般場(chǎng)景下常拓,hash和history都可以使用
history
①優(yōu)點(diǎn):如果你更在意顏值渐溶,那么就使用沒(méi)有#的history模式,這種模式充分利用history.pushState? API來(lái)完成url的跳轉(zhuǎn)弄抬,而且不需要重新加載頁(yè)面茎辐,通過(guò)pushState()設(shè)置的url可以是和當(dāng)前url同源的任意url,甚至可以與當(dāng)前url一模一樣,它通過(guò)stateObject參數(shù)可以添加任意類(lèi)型的數(shù)據(jù)到記錄中掂恕,它還可以額外設(shè)置title屬性拖陆,提供給后續(xù)使用。利用pushState和replaceState方法懊亡,對(duì)歷史記錄進(jìn)行修改
缺點(diǎn):就是如果通過(guò)url向后端發(fā)起請(qǐng)求時(shí)依啰,尤其是在用戶手動(dòng)輸入url回車(chē)或者重新刷新(重啟)瀏覽器的時(shí)候,會(huì)報(bào)404錯(cuò)誤斋配,找不到指定路由孔飒,需要后端去指向正確的路由匹配, 比如當(dāng)url不匹配時(shí)跳轉(zhuǎn)到index.html,雖然通過(guò)以上兩種方法改變了當(dāng)前的url艰争,但是瀏覽器不會(huì)立即向后端發(fā)送請(qǐng)求
hash
②優(yōu)點(diǎn):回車(chē)刷新可以加載到hash值對(duì)應(yīng)的頁(yè)面坏瞄,并且支持低版本瀏覽器和IE瀏覽器,#/a雖然在url中甩卓,但不會(huì)被包括在http請(qǐng)求中鸠匀,對(duì)后端完全沒(méi)有影響,因此改變hash不會(huì)重新加載頁(yè)面逾柿。
缺點(diǎn):hash設(shè)置的新值必須與原來(lái)的不一樣才會(huì)出發(fā)動(dòng)作并且將記錄添加到棧中缀棍,它只可以修改#后面的部分宅此,所以只能設(shè)置與當(dāng)前url同文檔的url,只有短字符串才可以添加到記錄中