vue中 hash和history的區別


為什么要有hash 和history?

對於Vue這類漸進式前端開發框架,為了構建SPA(單頁面應用),需要引入前端路由系統,這也就是Vue-Router存在的意義。

前端路由的核心,就在於——改變試圖的同時不會向后端發出請求。

1:hash - 即地址欄URL中的 # 符號(此hash不是密碼學里的散列運算)
比如這個URL:http://www.abc.com/#/hello,hash的值為#/hello.它的特點在於:hash雖然出現在URL中,但不會被包括在HTTP請求中,對后端完全沒有影響,因此改變hash不會重新加載頁面。
2:history - 利用了HTML5 History Interface中新增的pushState()和replaceState()方法。(需要特定瀏覽器支持)

這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的backforwardgo的基礎上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改時,雖然改變了當前的URL,但瀏覽器不會即向后端發送請求。

因此可以說,hash模式和histoury模式都是屬於瀏覽器自身的特性,Vue-Router只是利用了這兩個特性(通過調用瀏覽器提供的接口)來實現前端路由

使用場景

一般情景下,hash和histoury都可以,除非你更在意顏值,#符號夾雜在URL里看起來確實有些不太美麗。如果不想要很丑的hash,我們可以用路由的history模式,這種模式充分利用history、pushState API來完成URL跳轉二無須重新加載頁面
調用history.pushState()相比於直接修改hash ,存在以下優勢:
1:pushState()設置的新URL可以是與當前URL同源的任意URL;而hash只可修改#后面的部分,因此只能設置與當前URL同文檔的URL;
2:pushState()設置的新URL可以與當前URL一模一樣,這樣也會把記錄添加到棧中;而hash設置的新值必須與原來不一樣才會觸發動作將記錄添加到棧中;
3:pushState()通過stateObject參數可以添加任意類型的數據到記錄中;而hash只可添加短字符串;
4:pushState()可額外設置title屬性供后續使用。

當然history也不是樣樣都好。SPA雖然在瀏覽器里游刃有余,單真要通過URL向后端發起HTTP請求時,兩者的差異就來了。尤其在用戶手動輸入URL后回車,或者刷新(重啟)瀏覽器的時候。
1:hash 模式下,僅hash符號之前的內容會被包含在請求中,如http://www.abc.com,因此對於后端來說,即使沒有做到對路由的全覆蓋,也不會返回404錯誤。
2:history模式下,前端的URL必須和實際向后端發起請求的URL一致。如htttp://www.abc.com/book/id。如果后端缺少對/book/id 的路由處理,將返回404錯誤,

那么就需要和后端人配合讓他配置一下apache或是nginx的url重定向,重定向到你的首頁路由上就ok啦。

路由模式配置:

1 export default new Router({
2     // mode: 'history',
3     mode: 'hash',
4     routes
5 })

如果是 history模式需要后端配合解決刷新404問題 這里以Node 后台為例:

復制代碼
 1 const Koa = require('koa')
 2 const Router = require('koa-router');
 3 const static = require('koa-static')
 4 const fs = require('fs');
 5 const app = new Koa();
 6 const router = new Router();
 7 
 8 let str;
 9 fs.readFile('../dist/index.html', "utf-8", (err, data) => {
10     if (err) {
11         ctx.body = "error found"
12     }
13     str = data.toString();
14 })
15 
16 // 解決vue 路由在 history刷新 404情況
17 router.get('*', async(ctx, next) => {
18     if (ctx.url !== "/index.html") {
19         console.log("在這里返回")
20         ctx.body = str;
21     } 
22 })
23 
24 app.use(static("../dist/"));
25 app.use(router.routes()) //啟動路由
26 app.use(router.allowedMethods());
27 
28 
29 app.listen(8989, () => {
30     console.log("監聽服務器地址:127.0.0.1:8989");
31 })
復制代碼
history修改歷史狀態

包括了pushState,replaceState兩個方法,這兩個方法接收三個參數:stateObj,title,url

1
2
3
4
5
6
7
8
9
history.pushState({color: 'red' }, 'red' , 'red' })
window.onpopstate = function (event){
   console.log(event.state)
   if (event.state && event.state.color === 'red' ){
     document.body.style.color = 'red' ;
   }
}
history.back();
history.forward();

通過pushstate把頁面的狀態保存在state對象中,當頁面的url再變回這個url時,可以通過event.state取到這個state對象,從而可以對頁面狀態進行還原,這里的頁面狀態就是頁面字體顏色,其實滾動條的位置,閱讀進度,組件的開關的這些頁面狀態都可以存儲到state的里面。

history模式怕啥

通過history api,我們丟掉了丑陋的#,但是它也有個毛病:

 不怕前進,不怕后退,就怕刷新,f5,(如果后端沒有准備的話),因為刷新是實實在在地去請求服務器的,不玩虛的。

在hash模式下,前端路由修改的是#中的信息,而瀏覽器請求時是不帶它玩的,所以沒有問題.但是在history下,你可以自由的修改path,當刷新時,如果服務器中沒有相應的響應或者資源,會分分鍾刷出一個404來。

所以,如果你想在github.io上搭一個單頁博客,就應該選擇hash模式。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM