單頁應用(SinglePage Application,SPA)
指只有一個主頁面的應用,一開始只需加載一次
js,css
等相關資源。所有的內容都包含在主頁面,對每一個功能模塊組件化。單頁應用跳轉,就是切換相關組件,僅刷新局部資源。
多頁應用(MultiPage Application,MPA)
指有多個獨立的頁面的應用,每個頁面必須重復加載
js,css
等相關資源。多頁應用跳轉,需要整頁資源刷新。
兩者對比表格:
SPA | MPA | |
---|---|---|
結構 | 一個主頁面 + 許多模塊的組件 | 許多完整的頁面 |
體驗 | 頁面切換快,體驗佳;當初次加載文件過多時,需要做相關的調優。 | 頁面切換慢,網速慢的時候,體驗尤其不好 |
資源文件 | 組件公用的資源只需要加載一次 | 每個頁面都要自己加載公用的資源 |
適用場景 | 對體驗度和流暢度有較高要求的應用,不利於 SEO(可借助 SSR 優化 SEO) | 適用於對 SEO 要求較高的應用 |
過渡動畫 | Vue 提供了 transition 的封裝組件,容易實現 | 很難實現 |
內容更新 | 相關組件的切換,即局部更新 | 整體 HTML 的切換,費錢(重復 HTTP 請求) |
路由模式 | 可以使用 hash ,也可以使用 history | 普通鏈接跳轉 |
數據傳遞 | 因為單頁面,使用全局變量就好(Vuex) | cookie 、localStorage 等緩存方案,URL 參數,調用接口保存等 |
相關成本 | 前期開發成本較高,后期維護較為容易 | 前期開發成本低,后期維護就比較麻煩,因為可能一個功能需要改很多地方 |
單頁應用實現核心:前端路由
前端路由的核心:改變視圖的同時不會向后端發出請求。
這里我講講 vue-router 路由的兩種模式:hash&history
1、hash 模式
hash 模式背后的原理是 onhashchange
事件。
-
window.addEventListener( hashchange ,function(e) {
-
console.log(e.oldURL);
-
console.log(e.newURL)
-
},false);
通過
window.location.hash
屬性獲取和設置hash
值。
由於 hash 發生變化的 url 都會被瀏覽器記錄下來,所以瀏覽器的前進后退可以使用,盡管瀏覽器沒有請求服務器,但是頁面狀態和 url 關聯起來。后來人們稱其為前端路由,成為單頁應用標配。
hash 模式的特點在於 hash 出現在 url 中,但是不會被包括在 HTTP 請求中,對后端沒有影響,不會重新加載頁面。
2、history 模式
利用了 HTML5 History Interface 中新增的
pushState()
和replaceState()
,它們提供了對歷史記錄進行修改的功能。
相關的 API:
history.pushState()
-
history.pushState(stateObj, title, url);
- state:一個與指定網址相關的狀態對象,
popstate
事件觸發時,該對象會傳入回調函數。如果不需要可填null
。 - title:新頁面的標題,但是所有瀏覽器目前都忽略這個值,可填
null
。 - url:新的網址,必須與當前頁面處在同一個域。瀏覽器的地址欄將顯示這個網址。
例如:
history.pushState(new,new,new.html);
添加上面這個新記錄后,瀏覽器地址欄立刻顯示 ~/new.html
,但並不會跳轉到 new.html
,它只是成為 history
中的最新記錄。pushState
方法不會觸發頁面刷新,只是 history
對象變化,地址欄會變。
history.replaceState()
-
history.replaceState(stateObj, title, url);
參數同 pushState()
一樣。
調用該方法,會修改當前的 history
對象記錄, history.length
的長度不會改變
history.state
當前 URL 下對應的狀態信息。如果當前 URL 不是通過 pushState
或者 replaceState
產生的,那么 history.state
是 null
。當需要 state 和 URL 同步時可以使用 replaceState()
使之同步。
popstate 事件
同一個文檔的
history
對象出現變化時,就會觸發popstate
事件。
不同的瀏覽器在加載頁面時處理 popstate
事件的形式存在差異。頁面加載時 Chrome 和 Safari 通常會觸發 popstate 事件,但 Firefox 則不會。
注意:調用 history.pushState()
或者 history.replaceState()
不會觸發 popstate
事件。 popstate
事件只會在瀏覽器某些行為下觸發, 比如點擊后退、前進按鈕(或者調用 history.back()、history.forward()、history.go()
方法)。