<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                隨著移動網絡的發展與演化,我們手機上現在除了有原生 App,還能跑“WebApp”——它即開即用,用完即走。一個優秀的 WebApp 甚至可以擁有和原生 App 媲美的功能和體驗。 我認為,WebApp 就是我們前端性能優化的產物,是我們前端工程師對體驗不懈追求的結果,是 Web 網頁在性能上向 Native 應用的一次“宣戰”。 WebApp 優異的性能表現,要歸功于瀏覽器存儲技術的廣泛應用——這其中除了我們上節提到的緩存,本地存儲技術也功不可沒。 ## 故事的開始:從 Cookie 說起 Cookie 的本職工作并非本地存儲,而是“維持狀態”。 在 Web 開發的早期,人們亟需解決的一個問題就是狀態管理的問題:HTTP 協議是一個無狀態協議,服務器接收客戶端的請求,返回一個響應,故事到此就結束了,服務器并沒有記錄下關于客戶端的任何信息。那么下次請求的時候,如何讓服務器知道“我是我”呢? 在這樣的背景下,Cookie 應運而生。 Cookie 說白了就是一個存儲在瀏覽器里的一個小小的文本文件,它附著在 HTTP 請求上,在瀏覽器和服務器之間“飛來飛去”。它可以攜帶用戶信息,當服務器檢查 Cookie 的時候,便可以獲取到客戶端的狀態。 關于 Cookie 的詳細內容,我們可以在 Chrome 的 Application 面板中查看到: ![](https://user-gold-cdn.xitu.io/2018/9/22/166002bebabcf363?w=1916&h=904&f=png&s=257061) 如大家所見,**Cookie 以鍵值對的形式存在**。 ### Cookie的性能劣勢 #### Cookie 不夠大 大家知道,Cookie 是有體積上限的,它最大只能有 4KB。當 Cookie 超過 4KB 時,它將面臨被裁切的命運。這樣看來,Cookie 只能用來存取少量的信息。 #### 過量的 Cookie 會帶來巨大的性能浪費 **Cookie 是緊跟域名的**。我們通過響應頭里的 Set-Cookie 指定要存儲的 Cookie 值。默認情況下,domain 被設置為設置 Cookie 頁面的主機名,我們也可以手動設置 domain 的值: ``` Set-Cookie: name=xiuyan; domain=xiuyan.me ``` **同一個域名下的所有請求,都會攜帶 Cookie**。大家試想,如果我們此刻僅僅是請求一張圖片或者一個 CSS 文件,我們也要攜帶一個 Cookie 跑來跑去(關鍵是 Cookie 里存儲的信息我現在并不需要),這是一件多么勞民傷財的事情。Cookie 雖然小,請求卻可以有很多,隨著請求的疊加,這樣的不必要的 Cookie 帶來的開銷將是無法想象的。 隨著前端應用復雜度的提高,Cookie 也漸漸演化為了一個“存儲多面手”——它不僅僅被用于維持狀態,還被塞入了一些亂七八糟的其它信息,被迫承擔起了本地存儲的“重任”。在沒有更好的本地存儲解決方案的年代里,Cookie 小小的身體里承載了 4KB 內存所不能承受的壓力。 為了彌補 Cookie 的局限性,讓“專業的人做專業的事情”,Web Storage 出現了。 ## 向前一步:Web Storage Web Storage 是 HTML5 專門為瀏覽器存儲而提供的數據存儲機制。它又分為 Local Storage 與 Session Storage。這兩組概念非常相近,我們不妨先理解它們之間的區別,再對它們的共性進行研究。 ### Local Storage 與 Session Storage 的區別 兩者的區別在于**生命周期**與**作用域**的不同。 * 生命周期:Local Storage 是持久化的本地存儲,存儲在其中的數據是永遠不會過期的,使其消失的唯一辦法是手動刪除;而 Session Storage 是臨時性的本地存儲,它是會話級別的存儲,當會話結束(頁面被關閉)時,存儲內容也隨之被釋放。 * 作用域:Local Storage、Session Storage 和 Cookie 都遵循同源策略。但 Session Storage 特別的一點在于,即便是相同域名下的兩個頁面,只要它們**不在同一個瀏覽器窗口中**打開,那么它們的 Session Storage 內容便無法共享。 ### Web Storage 的特性 * 存儲容量大: Web Storage 根據瀏覽器的不同,存儲容量可以達到 5-10M 之間。 * 僅位于瀏覽器端,不與服務端發生通信。 ### Web Storage 核心 API 使用示例 Web Storage 保存的數據內容和 Cookie 一樣,是文本內容,以鍵值對的形式存在。Local Storage 與 Session Storage 在 API 方面無異,這里我們以 localStorage 為例: * 存儲數據:setItem() ``` localStorage.setItem('user_name', 'xiuyan') ``` * 讀取數據: getItem() ``` localStorage.getItem('user_name') ``` * 刪除某一鍵名對應的數據: removeItem() ``` localStorage.removeItem('user_name') ``` * 清空數據記錄:clear() ``` localStorage.clear() ``` ### 應用場景 #### Local Storage Local Storage 在存儲方面沒有什么特別的限制,理論上 Cookie 無法勝任的、可以用簡單的鍵值對來存取的數據存儲任務,都可以交給 Local Storage 來做。 這里給大家舉個例子,考慮到 Local Storage 的特點之一是**持久**,有時我們更傾向于用它來存儲一些內容穩定的資源。比如圖片內容豐富的電商網站會用它來存儲 Base64 格式的圖片字符串: ![](https://user-gold-cdn.xitu.io/2018/9/22/16600d07e6abdd81?w=1980&h=518&f=png&s=278919) 有的網站還會用它存儲一些不經常更新的 CSS、JS 等靜態資源。 #### Session Storage Session Storage 更適合用來存儲生命周期和它同步的**會話級別**的信息。這些信息只適用于當前會話,當你開啟新的會話時,它也需要相應的更新或釋放。比如微博的 Session Storage 就主要是存儲你本次會話的瀏覽足跡: ![](https://user-gold-cdn.xitu.io/2018/9/29/16623d7a9457d1df?w=1597&h=696&f=jpeg&s=68226) lasturl 對應的就是你上一次訪問的 URL 地址,這個地址是即時的。當你切換 URL 時,它隨之更新,當你關閉頁面時,留著它也確實沒有什么意義了,干脆釋放吧。這樣的數據用 Session Storage 來處理再合適不過。 這樣看來,Web Storage 確實也夠強大了。那么 Web Storage 是否能 hold 住所有的存儲場景呢? 答案是否定的。大家也看到了,Web Storage 是一個從定義到使用都非常簡單的東西。它使用鍵值對的形式進行存儲,這種模式有點類似于對象,卻甚至連對象都不是——它只能存儲字符串,要想得到對象,我們還需要先對字符串進行一輪解析。 說到底,Web Storage 是對 Cookie 的拓展,它只能用于存儲少量的簡單數據。當遇到大規模的、結構復雜的數據時,Web Storage 也愛莫能助了。這時候我們就要清楚我們的終極大 boss——IndexDB! ## 終極形態:IndexDB IndexDB 是一個**運行在瀏覽器上的非關系型數據庫**。既然是數據庫了,那就不是 5M、10M 這樣小打小鬧級別了。理論上來說,IndexDB 是沒有存儲上限的(一般來說不會小于 250M)。它不僅可以存儲字符串,還可以存儲二進制數據。 IndexDB 從推出之日起,其優質教程就層出不絕,我們今天不再著重講解它的詳細操作。接下來,我們遵循 MDN 推薦的操作模式,通過一個基本的 IndexDB 使用流程,旨在對 IndexDB 形成一個感性的認知: 1. 打開/創建一個 IndexDB 數據庫(當該數據庫不存在時,open 方法會直接創建一個名為 xiaoceDB 新數據庫)。 ``` // 后面的回調中,我們可以通過event.target.result拿到數據庫實例 let db // 參數1位數據庫名,參數2為版本號 const request = window.indexedDB.open("xiaoceDB", 1) // 使用IndexDB失敗時的監聽函數 request.onerror = function(event) { console.log('無法使用IndexDB') } // 成功 request.onsuccess = function(event){ // 此處就可以獲取到db實例 db = event.target.result console.log("你打開了IndexDB") } ``` 2. 創建一個 object store(object store 對標到數據庫中的“表”單位)。 ``` // onupgradeneeded事件會在初始化數據庫/版本發生更新時被調用,我們在它的監聽函數中創建object store request.onupgradeneeded = function(event){ let objectStore // 如果同名表未被創建過,則新建test表 if (!db.objectStoreNames.contains('test')) { objectStore = db.createObjectStore('test', { keyPath: 'id' }) } } ``` 3. 構建一個事務來執行一些數據庫操作,像增加或提取數據等。 ``` // 創建事務,指定表格名稱和讀寫權限 const transaction = db.transaction(["test"],"readwrite") // 拿到Object Store對象 const objectStore = transaction.objectStore("test") // 向表格寫入數據 objectStore.add({id: 1, name: 'xiuyan'}) ``` 4. 通過監聽正確類型的事件以等待操作完成。 ``` // 操作成功時的監聽函數 transaction.oncomplete = function(event) { console.log("操作成功") } // 操作失敗時的監聽函數 transaction.onerror = function(event) { console.log("這里有一個Error") } ``` ### IndexDB 的應用場景 通過上面的示例大家可以看出,在 IndexDB 中,我們可以創建多個數據庫,一個數據庫中創建多張表,一張表中存儲多條數據——這足以 hold 住復雜的結構性數據。IndexDB 可以看做是 LocalStorage 的一個升級,當數據的復雜度和規模上升到了 LocalStorage 無法解決的程度,我們毫無疑問可以請出 IndexDB 來幫忙。 ## 小結 瀏覽器緩存/存儲技術的出現和發展,為我們的前端應用帶來了無限的轉機。近年來基于緩存/存儲技術的第三方庫層出不絕,此外還衍生出了 [PWA](https://lavas.baidu.com/pwa) 這樣優秀的 Web 應用模型。可以說,現代前端應用,尤其是移動端應用,之所以可以發展到在體驗上叫板 Native 的地步,主要就是仰仗緩存/存儲立下的汗馬功勞。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看