1. SPA
SPA(Single-page Web applications):單頁面應用。指的是只有一個Web頁面的應用,是加載單個HTML頁面,并在用戶與應用程序交互時動態(tài)更新該頁面的Web應用程序。
通俗點講就是在一個項目中,只有一個html頁面,它在第一次加載頁面時,將唯一完成的html頁面和所有其余頁面組件一起下載下來,所有的組件的展示與切換都在這唯一的頁面中完成,當切換頁面時,不會重新加載整個頁面,而是通過路由來實現(xiàn)不同組件之間的切換,更新某個指定的容器中的內(nèi)容。
SPA的優(yōu)點:
- 更新視圖而不會重新請求頁面
- 最有桌面應用的即時性、網(wǎng)站的可移植性和可訪問性
- 用戶體驗好、快,內(nèi)容的改變不需要重新加載整個頁面
- 良好的錢后端分離,分工更明確
SPA的缺點:
- 不利于搜索引擎的抓取
- 首次渲染速度相對較慢
2. Vue-Router
Vue-Router是Vue.js官方的路由插件。Vue的單頁面應用是基于路由和組件的,路由用于設定訪問路徑,并將路徑和組件映射起來。傳統(tǒng)的頁面應用,是用一些超鏈接來實現(xiàn)頁面切換和跳轉的。在單頁面應用中,頁面跳轉和切換就是組件的切換。路由模塊的本質就是建立起url和頁面之間的映射關系。
路由器對象底層實現(xiàn)的三大步驟:
- 監(jiān)視地址欄變化;
- 查找當前路徑對應的頁面組件;
- 將找到的頁面組件替換到router-view的位置;
Vue-Router在實現(xiàn)單頁面路由時,提供了兩種方式:Hash模式和History模式,可以在創(chuàng)建router時選擇不同的模式:
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(), // 這里指定具體的模式
routes, // `routes: routes` 的縮寫
})
2.1 Hash模式
Vue-Router的Hash模式,使用URL的hash來模擬一個完整的URL,當URL改變時,頁面不會重新加載;# 就是hash富豪,在hash符號后的值稱為hash值;
首先我們需要了解下window.onhashchange:https://www.runoob.com/jsref/event-onhashchange.html。當改變hash值的時候,可以通過window.onhashchange監(jiān)聽到這個變化:
<body>
<button onclick="changeHash()">改變hash值</button>
<script>
function changeHash() {
window.location.hash = "account"
}
window.onhashchange = function () {
console.log(`監(jiān)聽到hash值修改:${window.location.href}`);
}
</script>
</body>
// 輸出的值為:http://127.0.0.1:5500/javascript/254.history.html#account
Hash模式其實就是利用了window可以監(jiān)聽onhashchange事件來實現(xiàn)的。hash值是用來指導瀏覽器動作,對服務器沒有影響,HTTP請求中不會包括hash值,同時每一次改變hash值,都會在瀏覽器的訪問歷史中增加一個記錄,使用“后退”按鈕,就可以回到上一個位置。所以,Hash模式是根據(jù)hash值來發(fā)生改變,根據(jù)不同的值,渲染指定DOM位置的不同數(shù)據(jù)。
Hash模式的特點:
- url中會帶有一個#號
- 可以改變URL,但是不會觸發(fā)頁面的重新加載(hash的改變會記錄在 window.hisotry 中)因此并不算是一次 HTTP 請求,所以這種模式不利于 SEO 優(yōu)化
- 只能修改#后面的部分,因此只能跳轉與當前URL同文檔的URL
- 只能通過字符串改變URL
- 通過window.onhashchange監(jiān)聽hash的改變,借此實現(xiàn)無刷新跳轉的功能
- 每改變一次hash(window.location.hash),都會在瀏覽器的訪問歷史中增加一個記錄
- 路徑從#開始,后面的所有路徑都叫做路由的哈希值,并且哈希值它不會作為路徑的一部分隨著http請求,發(fā)給服務器
2.2 History模式
History模式是Vue-Router的另一種模式。它是通過調用window.history對象上的一系列方法來實現(xiàn)頁面的無刷新跳轉。
利用了HTML5 History Interface中新增的pushState()和replaceState()方法,這兩個方法應用于瀏覽器的歷史記錄棧,在當前已有的back、forward、go的基礎上,他們提供了對歷史記錄進行修改的功能。只是當它們執(zhí)行修改時,雖然改變了當前的URL,但是瀏覽器不會向后端發(fā)送請求。
2.2.1 history.pushState
2.2.1.1 簡介
history.pushState是HTML5提供的一個新特性,它允許我們改變?yōu)g覽器地址欄的url,并且不會像傳統(tǒng)的URL跳轉那樣重新加載整個頁面。
2.2.1.2 使用方法
history.pushState的使用方法非常簡單。需要三個參數(shù):state、title、url:
- state是一個js對象,可以存儲一些與URL相關的數(shù)據(jù)
- title是一個字符串,通常被瀏覽器用于顯示頁面標題
- url是一個包含當前url的字符串
下面是一個代碼示例:
history.pushState({page: "settings"}, "Settings", "/settings");
上面的代碼將當前URL改成了/settings,同時還傳入了一個名為page的數(shù)據(jù)對象,這個對象會被存儲到瀏覽器的會話歷史中,以便后續(xù)使用。需要注意的是,調用pushState并不會導致瀏覽器加載新的頁面或刷新現(xiàn)有頁面。
2.2.1.3 注意事項
- pushState調用不會觸發(fā)頁面加載事件及其它事件的處理函數(shù)
在調用history.pushState時,瀏覽器地址欄的URL會更新,但是瀏覽器并不會像傳統(tǒng)的URL跳轉那樣重新加載整個頁面。如果需要在頁面的URL改變時執(zhí)行一些特殊的操作,例如加載新的內(nèi)容,需要綁定一個popstate事件處理函數(shù):
window.addEventListener('popstate', function(e) {
console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
});
pushState調用無法阻止用戶使用后退按鈕
當用戶點擊瀏覽器的后退按鈕時,瀏覽器會返回上一個歷史記錄條目,這會導致頁面的URL發(fā)生改變。盡管調用pushState方法改變了URL,但無法阻止用戶使用后退按鈕。如果你希望阻止用戶使用后退按鈕,需要在popstate事件中執(zhí)行特殊的操作。pushState調用可能導致404錯誤
如果直接使用history.pushState更新URL,但是并沒有相應的服務器端處理,那么在用戶刷新頁面或者直接訪問該URL時會導致404錯誤。因此,需要在服務端進行相應的配置,讓服務端能夠正確處理這些URL請求,返回相應的內(nèi)容。
使用history.pushState可以實現(xiàn)改變URL而不會發(fā)生頁面刷新,這也是History模式實現(xiàn)的基礎。
2.2.2 History模式的特點
- 路由跳轉不需要重新加載頁面
- 不帶#,看起來比hash路由好看很多
- 兼容性沒有hash好,可以看上面pushState的注意事項
2.2.3 問題及解決
2.2.3.1 生產(chǎn)環(huán)境
當我們把history項目部署到服務器后,此時我們在瀏覽器中輸入一個網(wǎng)址(www.test.com),此時會經(jīng)過DNS解析,拿到ip地址后根據(jù)ip地址向該服務器發(fā)起請求,服務器接收到請求之后,返回相應的數(shù)據(jù)(html css js)。如果我們在前端設置了重定向,跳轉到 www.test.com/home,在前端會進行匹配對應的組件然后將其渲染到頁面上。此時,如果我們刷新頁面的話,瀏覽器會發(fā)送新的請求:www.test.com/home,如果后端服務器沒有/home對應的接口,那么就會返回404.
生產(chǎn)環(huán)境刷新404的解決辦法可以在nginx做代理轉發(fā),在nginx中配置按順序檢查參數(shù)中的資源是否存在,如果都沒有找到,讓nginx內(nèi)部重定向到項目首頁。

2.2.3.2 開發(fā)環(huán)境-historyApiFallback
那為什么開發(fā)環(huán)境時就不會出現(xiàn)404呢?因為在vue-cli 中 webpack 幫我們做了處理:

3. 總結
至此我們使用知道了 vue-roter 的兩種路由模式,及差異化,簡單來講就是,hash 路由兼容性更好,但是帶#顯得丑些, histroy 和正常 url 路徑一樣,但是需要在服務器進行單獨配置。大家可以根據(jù)自己的喜好去按需使用。