天天看點

單頁應用 & 多頁應用的差別

最近看到一些人在問單頁面和多頁面應用的差別。是以也就輸出這一篇短文希望可以給你一個整體的認識。

這裡也會大體介紹單頁應用實作的核心 —— 前端路由。

單頁應用 & 多頁應用的差別

對比圖

單頁應用(SinglePage Application,SPA)

指隻有一個首頁面的應用,一開始隻需加載一次 <code>js,css</code> 等相關資源。所有的内容都包含在首頁面,對每一個功能子產品元件化。單頁應用跳轉,就是切換相關元件,僅重新整理局部資源。

多頁應用(MultiPage Application,MPA)

指有多個獨立的頁面的應用,每個頁面必須重複加載 <code>js,css</code> 等相關資源。多頁應用跳轉,需要整頁資源重新整理。

SPA

MPA

結構

一個首頁面 + 許多子產品的元件

許多完整的頁面

體驗

頁面切換快,體驗佳;當初次加載檔案過多時,需要做相關的調優。

頁面切換慢,網速慢的時候,體驗尤其不好

資源檔案

元件公用的資源隻需要加載一次

每個頁面都要自己加載公用的資源

适用場景

對體驗度和流暢度有較高要求的應用,不利于 SEO(可借助 SSR 優化 SEO)

适用于對 SEO 要求較高的應用

過渡動畫

Vue 提供了 transition 的封裝元件,容易實作

很難實作

内容更新

相關元件的切換,即局部更新

整體 HTML 的切換,費錢(重複 HTTP 請求)

路由模式

可以使用 hash ,也可以使用 history

普通連結跳轉

資料傳遞

因為單頁面,使用全局變量就好(Vuex)

cookie 、localStorage 等緩存方案,URL 參數,調用接口儲存等

相關成本

前期開發成本較高,後期維護較為容易

前期開發成本低,後期維護就比較麻煩,因為可能一個功能需要改很多地方

前端路由的核心:改變視圖的同時不會向後端送出請求。

這裡我講講 vue-router 路由的兩種模式:<code>hash&amp;history</code>

hash 模式背後的原理是 <code>onhashchange</code> 事件。

通過 <code>window.location.hash</code> 屬性擷取和設定 <code>hash</code> 值。

由于 hash 發生變化的 url 都會被浏覽器記錄下來,是以浏覽器的前進後退可以使用,盡管浏覽器沒有請求伺服器,但是頁面狀态和 url 關聯起來。後來人們稱其為前端路由,成為單頁應用标配。

hash 模式的特點在于 hash 出現在 url 中,但是不會被包括在 HTTP 請求中,對後端沒有影響,不會重新加載頁面。
利用了 HTML5 History Interface 中新增的 <code>pushState()</code> 和 <code>replaceState()</code>,它們提供了對曆史記錄進行修改的功能。

相關的 API:

state:一個與指定網址相關的狀态對象, <code>popstate</code> 事件觸發時,該對象會傳入回調函數。如果不需要可填 <code>null</code>。

title:新頁面的标題,但是所有浏覽器目前都忽略這個值,可填 <code>null</code>。

url:新的網址,必須與目前頁面處在同一個域。浏覽器的位址欄将顯示這個網址。

例如:<code>history.pushState(new,new,new.html);</code>

添加上面這個新記錄後,浏覽器位址欄立刻顯示 <code>~/new.html</code>,但并不會跳轉到 <code>new.html</code>,它隻是成為 <code>history</code> 中的最新記錄。<code>pushState</code> 方法不會觸發頁面重新整理,隻是 <code>history</code> 對象變化,位址欄會變。

參數同 <code>pushState()</code> 一樣。

調用該方法,會修改目前的 <code>history</code> 對象記錄, <code>history.length</code> 的長度不會改變

目前 URL 下對應的狀态資訊。如果目前 URL 不是通過 <code>pushState</code> 或者 <code>replaceState</code> 産生的,那麼 <code>history.state</code>是 <code>null</code>。當需要 state 和 URL 同步時可以使用 <code>replaceState()</code> 使之同步。

同一個文檔的 <code>history</code> 對象出現變化時,就會觸發 <code>popstate</code> 事件。

不同的浏覽器在加載頁面時處理 <code>popstate</code> 事件的形式存在差異。頁面加載時 Chrome 和 Safari 通常會觸發 popstate 事件,但 Firefox 則不會。

注意:調用 <code>history.pushState()</code> 或者 <code>history.replaceState()</code> 不會觸發 <code>popstate</code> 事件。 <code>popstate </code>事件隻會在浏覽器某些行為下觸發, 比如點選後退、前進按鈕(或者調用 <code>history.back()、history.forward()、history.go()</code>方法)。

單頁應用 &amp; 多頁應用的差別