什麼是單頁應用程式?

現代Web應用程式也被稱為單頁應用程式(Single Page Applications)。這是什麼意思? 在過去,當瀏覽器的功能比現在差得多,JavaScript的性能也很差時,每個頁面都是從服務器上請求的。每次點擊某些東西時,都會向服務器發送一個新的請求,然後瀏覽器會加載新的頁面。 只有非常創新的產品才會以不同的方式工作,並嘗試新的方法。 如今,受到像React這樣的現代前端JavaScript框架的推動,一個應用通常被構建為單頁應用程式:你只加載一次應用程式代碼(HTML,CSS,JavaScript),當你與應用程式交互時,通常發生的是JavaScript截取瀏覽器事件,而不是向服務器發送新的請求,然後返回一個新文檔,用戶看到的頁面從未完全被刷新,表現得更像桌面應用程式。 單頁應用程式是使用JavaScript構建的(或至少編譯為JavaScript),並在瀏覽器中運行。 技術總是一樣的,但應用程式的工作方式的哲學和一些關鍵組件是不同的。 單頁應用程式的一些例子 一些值得注意的例子: Gmail Google Maps Facebook Twitter Google Drive 單頁應用程式的優缺點 單頁應用程式對用戶來說感覺更快,因為不需要等待客戶端和服務器之間的通信,也不需要等待瀏覽器重新渲染頁面,現在可以立即獲得反饋。這是應用程式製造者的責任,但你可以使用過渡效果、旋轉圖示和任何一種優化用戶體驗的方式,這肯定比傳統的工作流程要好。 除了讓用戶體驗更快之外,服務器會消耗更少的資源,因為你可以專注於提供一個高效的API,而不是在服務器端構建佈局。 如果你還在API之上構建一個移動應用程式,那麼這將非常理想,因為你可以完全重用現有的服務器端代碼。 單頁應用程式易於轉化為漸進式Web應用程式(Progressive Web Apps),從而為你的服務提供本地緩存和支持離線體驗(或者如果用戶需要在線時提供更好的錯誤消息)。 當不需要搜索引擎優化(SEO)時,單頁應用程式是最合適的選擇。例如,對於需要登錄的應用程式。 儘管搜索引擎每天都在提升,但它們在索引使用單頁應用程式方法構建的網站時仍然存在問題,而不是傳統的服務器渲染頁面。這對於博客來說也是如此。如果你依賴搜索引擎,除非同時具有服務器呈現的部分,否則不要麻煩去創建一個單頁應用程式。 在編寫單頁應用程式時,你需要編寫大量的JavaScript。由於應用程式可能長時間運行,你需要更加注意可能的內存泄漏 - 如果在過去,你的頁面的壽命計算在幾分鐘內,那麼現在一個單頁應用可能會長時間打開,在這段時間內,如果有任何內存問題,它將使瀏覽器的內存使用量大大增加,並導致不愉快的緩慢體驗,如果不加以處理的話。 在團隊中工作時,單頁應用程式很棒。後端開發人員可以專注於API,而前端開發人員可以專注於創建最佳的用戶體驗,並利用後端構建的API。 作為缺點,單頁應用程式嚴重依賴於JavaScript。這可能會導致在低功率設備上運行應用程式時速度較慢。此外,有些訪問者可能會禁用JavaScript,你還需要考慮到你所構建的任何內容的可訪問性。 重寫導航 由於你摒棄了默認的瀏覽器導航,URL必須手動管理。 這部分被稱為路由器。一些框架已經為你處理了它們(例如Ember),其他的則需要使用能完成這項工作的庫(例如React Router)。 問題在哪裡?在開發單頁應用程式時,這曾經是開發者的一個事後考慮。這導致了常見的“後退按鈕失效”問題:當在應用程式中導航時,URL不會改變(因為瀏覽器的默認導航被劫持),當按下後退按鈕時,這通常是用戶返回到上一個屏幕的操作,卻可能跳到多年前的網站。 這個問題現在可以通過瀏覽器提供的History API解決,但大多數情況下,你會使用一個内部使用該API的庫,如React Router。tags:Single Page Applications, JavaScript, frontend frameworks

歷史API

歷史API是瀏覽器讓你與地址欄和導航歷史進行交互的方式。 介紹 訪問歷史API 導航歷史 向歷史記錄中添加條目 修改歷史記錄條目 訪問當前的歷史記錄條目狀態 onpopstate事件 介紹 歷史API允許你與瀏覽器歷史進行交互,觸發瀏覽器導航方法並更改地址欄的內容。 它在現代的單頁應用程序中特別有用,這種應用程序通常不會為新頁面發出服務器端請求,而只是內容發生變化而已。 如果一個在瀏覽器中運行的現代JavaScript應用程序不明確地或在框架層面上與歷史API進行交互,將會給用戶帶來很差的體驗,因為前進和後退按鈕將無法使用。 同時,當導航應用程序時,視圖會改變,但地址欄不會變化。 且刷新按鈕無法使用:刷新頁面時,由於缺少深度鏈接,瀏覽器會顯示一個不同的頁面。 歷史API是在HTML5引入的,並且現在所有現代瀏覽器都支持。IE自10版就支持,如果你需要支持IE9及更早版本,可使用History.js庫。 訪問歷史API 歷史API可在window對象上使用,所以你可以像這樣調用它:window.history或history,因為window是全局對象。 導航歷史 先從歷史API中最簡單的操作開始。 返回上一頁: history.back() 這將返回到會話歷史的前一個條目。你可以使用以下方式前往下一頁: history.forward() 這和使用瀏覽器的前進和後退按鈕是一樣的。 go()方‌​法可讓你多級路徑地返回或前進。例如: history.go(-1) //等同於`history.back()` history.go(-2) //等同於連續兩次調用`history.back()` history.go(1) //等同於`history.forward()` history.go(3) //等同於連續三次調用`history.forward()` 要知道歷史記錄中有多少條目,你可以調用: history.length 向歷史記錄中添加條目 使用 pushState() 方法可以以程式方式創建一個新的歷史記錄條目。你需要傳遞3個參數。 第一個參數是一個對象,可以包含任何內容(然而有大小限制並且對象需要可序列化)。 第二個參數目前由主要瀏覽器未用到,因此通常傳遞空字符串。 第三個參數是與新狀態相關聯的URL。請注意,該URL必須屬於與當前URL相同的起源域。 const state = { name: 'Flavio' } history.pushState(state, '', '/user') 調用此方法不會更改頁面的內容,也不會引起任何像更改window.location一樣的瀏覽器動作。 修改歷史記錄條目 pushState() 可以添加新的狀態到歷史記錄,而replaceState()則可以編輯當前的歷史記錄狀態。 history.pushState({}, '', '/posts') const state = { post: 'first' } history.pushState(state, '', '/post/first') const state = { post: 'second' } history....