當前位置: 妍妍網 > 碼農

面試率超高的瀏覽器本地儲存,看這篇就夠了

2024-03-19碼農

本文約 6500 字,預計閱讀需要 20 分鐘。

今天來聊一聊常見的瀏覽器數據儲存方案:localStorage、sessionStorage、IndexedDB、Cookies。

1. 概述

現代瀏覽器中提供了多種儲存機制,開啟瀏覽器的控制台(Mac 可以使用 Command + Option + J 快捷鍵,Windows 可以使用 Control + Shift + J 快捷鍵)。選擇 Application 索引標籤,可以在 Storage中 看到 Local Storage、Session Storage、IndexedDB、Web SQL、Cookies 等:

那數據儲存在瀏覽器中有什麽使用場景呢?在以下情況下,將數據儲存在瀏覽器中成為更可行的選擇:

  • 在瀏覽器儲存中保存套用狀態,比如保持使用者偏好(使用者特定的設定,例如亮模式或暗模式、字型大小等);

  • 建立離線工作的漸進式 Web 套用,除了初始下載和更新之外沒有伺服器端要求;

  • 緩存靜態套用資源,如 HTML、CSS、JS 和影像等;

  • 保存上一個瀏覽會話中的數據,例如儲存上一個會話中的購物車內容,待辦事項列表中的計畫,記住使用者是否以前登入過等。

  • 無論哪種方式,將這些資訊保存在客戶端可以減少額外且不必要的伺服器呼叫,並幫助提供離線支持。不過,需要註意,由於實作差異,瀏覽器儲存機制在不同瀏覽器中的行為可能會有所不同。除此之外,許多瀏覽器已刪除對 Web SQL 的支持,建議將現有用法遷移到 IndexedDB。

    所以下面我們將介紹 Local Storage、Session Storage、IndexedDB、Cookies 的使用方式、使用場景以及它們之間的區別。

    2. Web Storage

    (1)概述

    HTML5 引入了 Web Storage,這使得在瀏覽器中儲存和檢索數據變得更加容易。Web Storage API 為客戶端瀏覽器提供了安全儲存和輕鬆存取鍵值對的機制。Web Storage 提供了兩個 API 來獲取和設定純字串的鍵值對:

  • localStorage :用於儲存持久數據,除非使用者手動將其從瀏覽器中刪除,否則數據將終身儲存。即使使用者關閉視窗或索引標籤,它也不會過期;

  • sessionStorage :用於儲存臨時會話數據,頁面重新載入後仍然存在,關閉瀏覽器索引標籤時數據遺失。

  • (2)方法和內容

    Web Storage API 由 4 個方法 setItem() getItem() removeItem() clear() key() 和一個 length 內容組成,以 localStorage 為例:

  • setItem() :用於儲存數據,它有兩個參數,即 key value 。使用形式: localStorage.setItem(key, value)

  • getItem() :用於檢索數據,它接受一個參數 key,即需要存取其值的鍵。使用形式: localStorage.getItem(key) ;

  • removeItem() :用於刪除數據,它接受一個參數 key,即需要刪除其值的鍵。使用形式: localStorage.removeItem(key) ;

  • clear() :用於清除其中儲存的所有數據,使用形式: localStorage.clear() ;

  • key() :該方法用於獲取 localStorage 中數據的所有key,它接受一個數位作為參數,該數位可以是 localStorage 項的索引位置。

  • console.log(typeofwindow.localStorage) // Object
    // 儲存數據
    localStorage.setItem("colorMode""dark")
    localStorage.setItem("username""zhangsan")
    localStorage.setItem("favColor""green")
    console.log(localStorage.length) // 3
    // 檢索數據
    console.log(localStorage.getItem("colorMode")) // dark
    // 移除數據
    localStorage.removeItem("colorMode")
    console.log(localStorage.length) // 2
    console.log(localStorage.getItem("colorMode")) // null
    // 檢索鍵名
    window.localStorage.key(0); // favColor
    // 清空本地儲存
    localStorage.clear()
    console.log(localStorage.length) // 0



    localStorage 和 sessionStorage 都非常適合緩存非敏感套用數據。可以在需要儲存少量簡單值並不經常存取它們是使用它們。它們本質上都是 同步 的,並且會阻塞主 UI 執行緒,所以應該謹慎使用。

    (3)儲存事件

    我們可以在瀏覽器上監聽 localStorage 和 sessionStorage 的儲存變化。storage 事件在建立、刪除或更新計畫時觸發。偵聽器函式在事件中傳遞,具有以下內容:

  • newValue :當在儲存中建立或更新計畫時傳遞給 setItem() 的值。當從儲存中刪除計畫時,此值設定為 null。

  • oldValue :建立新計畫時,如果該鍵存在於儲存中,則該計畫的先前的值。

  • key :正在更改的計畫的鍵,如果呼叫 .clear(),則值為 null。

  • url :執行儲存操作的 URL。

  • storageArea :執行操作的儲存物件(localStorage 或 sessionStorage)。

  • 通常,我們可以使用 window.addEventListener("storage", func) 或使用 onstorage 內容(如 window.onstorage = func )來監聽 storage 事件:

    window.addEventListener('storage', e => {
    console.log(e.key);
    console.log(e.oldValu);
    console.log(e.newValue);
    });
    window.onstorage = e => {
    console.log(e.key);
    console.log(e.oldValu);
    console.log(e.newValue);
    });

    註意,該功能不會在發生更改的同一瀏覽器索引標籤上觸發,而是由同一域的其他開啟的索引標籤或視窗觸發。此功能用於同步同一域的所有瀏覽器索引標籤/視窗上的數據。因此,要對此進行測試,需要開啟同一域的另一個索引標籤。

    (4)儲存限制

    localStorage 和 sessionStorage 只能儲存 5 MB 的數據,因此需要確保儲存的數據不會超過此限制。

    localStorage.setItem('a'Array(1024 * 1024 * 5).join('a'))
    localStorage.setItem('b''a')
    // Uncaught DOMException: Failed to execute 'setItem' on 'Storage': Setting the value of `a` exceeded the quota.

    在上面的例子中,收到了一個錯誤,首先建立了一個5MB的大字串,當再添加其他數據時就報錯了。

    另外,localStorage 和 sessionStorage 只接受字串。可以透過 JSON.stringify JSON.parse 來解決這個問題:

    const user = {
    name : "zhangsan",
    age : 28,
    gender : "male",
    profession : "lawyer"
    };
    localStorage.setItem("user"JSON.stringify(user));
    localStorage.getItem("user"); // '{"name":"zhangsan","age":28,"gender":"male","profession":"lawyer"}'
    JSON.parse(localStorage.getItem("user")) // {name: 'zhangsan', age: 28, gender: 'male', profession: 'lawyer'}

    如果我們直接將一個物件儲存在 localStorage 中,那將會在儲存之前進行隱式型別轉換,將物件轉換為字串,再進行儲存:

    const user = {
    name : "zhangsan",
    age : 28,
    gender : "male",
    profession : "lawyer"
    };
    localStorage.setItem("user", user);
    localStorage.getItem("user"); // '[object Object]'

    Web Storage 使用了同源策略,也就是說,儲存的數據只能在同一來源上可用。如果域和子體相同,則可以從不同的索引標籤存取 localStorage 數據,而無法存取 sessionStorage 數據,即使它是完全相同的頁面。

    另外:

  • 無法在 web worker 或 service worker 中存取 Web Storage;

  • 如果瀏覽器設定為私密模式,將無法讀取到 Web Storage;

  • Web Storage 很容易被 XSS 攻擊,敏感資訊不應儲存在本地儲存中;

  • 它是同步的,這意味著所有操作都是一次一個。對於復雜套用,它會減慢套用的執行時間。

  • (5)範例

    下面來看一個使用 localStorage 的簡單範例,使用 localStorage 來儲存使用者偏好:

    <inputtype="checkbox"id="darkTheme"name="darkTheme"onclick='onChange(this);'>
    <labelfor="darkTheme">黑暗模式</label><br>

    html {
    background: white;
    }
    .dark {
    background: black;
    color: white;
    }

    functiontoggle(on{
    if (on) {
    document.documentElement. classList.add('dark'); 
    else {
    document.documentElement. classList.remove('dark');
    }
    }
    functionsave(on{
    localStorage.setItem('darkTheme', on.toString());
    }
    functionload() {
    return localStorage.getItem('darkTheme') === 'true';
    }
    functiononChange(checkbox{
    const value = checkbox.checked;
    toggle(value);
    save(value);
    }
    const initialValue = load();
    toggle(initialValue);
    document.querySelector('#darkTheme').checked = initialValue;


    這裏的程式碼很簡單,頁面上有一個單選框,選中按鈕時將頁面切換為黑暗模式,並將這個配置儲存在 localStorage 中。當下一次再初始頁面時,獲取 localStorage 中的主題設定。

    3. Cookie

    (1)Cookie 概述

    Cookie 主要用於身份驗證和使用者數據永續性。Cookie 與請求一起發送到伺服器,並在響應時發送到客戶端;因此,cookies 數據在每次請求時都會與伺服器交換。伺服器可以使用 cookie 數據向使用者發送個人化內容。嚴格來說,cookie 並不是客戶端儲存方式,因為伺服器和瀏覽器都可以修改數據。它是唯一可以在一段時間後自動使數據過期的方式。

    每個 HTTP 請求和響應都會發送 cookie 數據。儲存過多的數據會使 HTTP 請求更加冗長,從而使套用比預期更慢:

  • 瀏覽器限制 cookie 的大小最大為4kb,特定域允許的 cookie 數量為 20 個,並且只能包含字串;

  • cookie 的操作是同步的;

  • 不能透過 web workers 來存取,但可以透過全域 window 物件存取。

  • Cookie 通常用於會話管理、個人化以及跨網站跟蹤使用者行為。我們可以透過伺服端和客戶端設定和存取 cookie。Cookie 還具有各種內容,這些內容決定了在何處以及如何存取和修改它們,

    Cookie 分為兩種型別:

  • 會話 Cookie :沒有指定 Expires 或 Max-Age 等內容,因此在關閉瀏覽器時會被刪除;

  • 永續性 Cookie :指定 Expires 或 Max-Age 內容。這些 cookie 在關閉瀏覽器時不會過期,但會在特定日期 (Expires) 或時間長度 (Max-Age) 後過期。

  • (2)Cookie 操作

    下面先來看看如何存取和操作客戶端和伺服器上的 cookie。

    ① 客戶端(瀏覽器)

    客戶端 JavaScript 可以透過 document.cookie 來讀取當前位置可存取的所有 cookie。它提供了一個字串,其中包含一個以分號分隔的 cookie 列表,使用 key=value 格式。

    document.cookie;

    可以看到,在語雀主頁中獲取 cookie,結果中包含了登入的 cookie、語言、當前主題等。

    同樣,可以使用 document.cookie 來設定 cookie 的值,設定cookie也是用key=value格式的字串,內容用分號隔開:

    document.cookie = "hello=world; domain=example.com; Secure";

    這裏用到了兩個內容 SameSite 和 Secure,下面會介紹。如果已經存在同名的 cookie 內容,就會更新已有的內容值,如果不存在,就會建立一個新的 key=value。

    如果需要經常在客戶端處理 Cookie,建議使用像 js-cookie 這樣的庫來處理客戶端 cookie:

    Cookies.set('hello''world', { domain'example.com'securetrue });
    Cookies.get('hello'); // -> world

    這樣不僅為 cookie 上的 CRUD 操作提供了一個幹凈的 API,而且還支持 TypeScript,從而幫助避免內容的拼寫錯誤。

    ② 伺服端(Node.js)

    伺服端可以透過 HTTP 請求的請求頭和響應頭來存取和修改 cookie。每當瀏覽器向伺服端發送 HTTP 請求時,它都會使用 cookie 頭將所有相關 cookie 都附加到該站點。請求檔頭是一個分號分隔的字串。

    這樣就可以從請求頭中讀取這些 cookie。如果在伺服端使用 Node.js,可以像下面這樣從請求物件中讀取它們,將獲得以分號分隔的 key=value 對:

    http.createServer(function (request, response{
    const cookies = request.headers.cookie;
    // "cookie1=value1; cookie2=value2"
    ...
    }).listen(8124);

    如果想要設定 cookie,可以在響應頭中添加 Set-Cookie 頭,其中 cookie 采用 key=value 的格式,內容用分號分隔:

    response.writeHead(200, {
    'Set-Cookie''mycookie=test; domain=example.com; Secure'
    });

    通常我們不會直接編寫 Node.js,而是與 ExpressJS 這樣的 Node.js 框架一起使用。使用 Express 可以更輕松地存取和修改 cookie。只需添加一個像 cookie-parser 這樣的中介軟體,就可以透過 req.cookies 以 JavaScript 物件的形式獲得所有的 cookie。還可以使用 Express 內建的 res.cookie() 方法來設定 cookie:

    const express = require('express')
    const cookieParser = require('cookie-parser')
    const app = express()
    app.use(cookieParser())
    app.get('/'function (req, res{
    console.log('Cookies: ', req.cookies)
    // Cookies: { cookie1: 'value1', cookie2: 'value2' }
    res.cookie('name''tobi', { domain'example.com'securetrue })
    })
    app.listen(8080)


    (3)Cookie 內容

    下面來深入了解 cookie 的內容。除了名稱和值之外,cookie 還具有控制很多方面的內容,包括安全方面、生命周期以及它們在瀏覽器中的存取位置和方式等。

    ① Domain

    Domain 內容告訴瀏覽器允許哪些主機存取 cookie。如果未指定,則預設為設定 cookie 的同一主機。因此,當使用客戶端 JavaScript 存取 cookie 時,只能存取與 URL 域相同的 cookie。同樣,只有與 HTTP 請求的域共享相同域的 cookie 可以與請求頭一起發送到伺服端。

    註意,擁有此內容並不意味著可以為任何域設定 cookie,因為這顯然會帶來巨大的安全風險。此內容存在的唯一原因就是 減少域的限制並使 cookie 在子體上可存取 。例如,如果當前的域是 abc.xyz.com,並且在設定 cookie 時如果不指定 Domain 內容,則預設為 abc.xyz.com,並且 cookie 將僅限於該域。但是,可能希望相同的 cookie 也可用於其他子體,因此可以設定 Domain=xyz.com 以使其可用於其他子體,如 def.xyz.com 和主域 xyz.com。

    ② Path

    此內容指定存取 cookie 必須存在的請求 URL 中的路徑。除了將 cookie 限制到域之外,還可以透過路徑來限制它。路徑內容為 Path=/store 的 cookie 只能在路徑 /store 及其子路徑 /store/cart、/store/gadgets 等上存取。

    ③ Expires/Max-size

    該內容用來設定 cookie 的過期時間。若設定其值為一個時間,那麽當到達此時間後,cookie 就會失效。不設定的話預設值是 Session,意思是cookie會和session一起失效。當瀏覽器關閉(不是瀏覽器分頁) 後,cookie 就會失效。

    除此之外,它還可以透過將過期日期設定為過去來刪除 cookie。

    ④ Secure

    具有 Secure 內容的 cookie 僅可以透過安全的 HTTPS 協定發送到伺服器,而不會透過 HTTP 協定。這有助於透過使 cookie 無法透過不安全的連線存取來防止中間人攻擊。除非網站實用不安全的 HTTP 連線,否則應該始終將此內容與所有 cookie 一起使用。

    ⑤ HTTPOnly

    此內容使 cookie 只能透過伺服端存取。因此,只有服務斷可以透過響應頭設定它們,然後瀏覽器會將它們與每個後續請求的頭一起發送到伺服器,並且它們將無法透過客戶端 JavaScript 存取。

    這可以在一定程度上幫助保護帶有敏感資訊(如身份驗證 token)的 cookie 免受 XSS 攻擊,因為任何客戶端指令碼都無法讀取 cookie。但這並不意味著可以完全免受 XSS 攻擊。因為,如果攻擊者可以在網站上執行第三方指令碼,那可能無法存取 cookie,相反,他們可以直接向伺服端執行相關的 API 請求。因此,想象一下使用者存取了一個頁面,黑客在網站上註入了惡意指令碼。他們可以使用該指令碼執行任何 API,並在他們不知道的情況下代表使用者執行操作。

    (4)Cookie 工具庫

    ① Js Cookie(JavaScript)

    Js Cookie 是一個簡單、輕量級的 JavaScript API,用於處理瀏覽器 cookie。其支持 AMD、CommonJS 和 ES 模組、沒有依賴關系、經過徹底測試、支持自訂編碼和解碼、通用瀏覽器支持。

    安裝:

    npm i js-cookie

    使用:

    // 設定 Cookie
    Cookies.set('cookie-name''cookie-value', { expires14})
    // 讀取 Cookie
    Cookies.get('cookie-name')
    // 刪除 Cookie
    Cookies.remove('cookie-name')

    ② React Cookie(React)

    React Cookie 是一個專門用於 React 的 cookie 庫,它繼承了 Universal Cookie 庫的功能。它提供了一組元件和 Hooks,使 React 中的 cookie 處理非常簡單。如果使用的是 React 16.8+ 版本,就可以使用 hooks 來處理 cookie。否則,必須使用其提供的元件。

    安裝:

    npm i react-cookie

    React Cookie 提供了 3 個 Hook,分別是 cookie、setCookie 和 removeCookie。可以使用這些 Hook 來處理 React 套用中的 cookie。

    const [cookies, setCookie, removeCookie] = useCookies(['cookie-name']);
    // 設定 Cookie
    setCookie(name, value, [options]);
    // 刪除 Cookie
    removeCookie(name, [options])

    ③ Cookies(Node.js)

    Cookies 是用於 HTTP cookie 配置的流行 NodeJS 模組之一。可以輕松地將其與內建的 NodeJS HTTP 庫整合或將其用作 Express 中介軟體。它允許使用 Keygrip 對 cookie 進行簽名以防止篡改、支持延遲 cookie 驗證、不允許透過不安全的套接字發送安全 cookie、允許其他庫在不知道簽名機制的情況下存取 cookie。

    安裝:

    npm install cookies

    使用:

    const cookie = require('cookie');
    cookies = new Cookies( request, response, [ options ] )
    // 讀取 cookies
    cookies.get( name, [ options ] )
    // 設定 cookies
    cookies.set( name, [ value ], [ options ] )

    4. IndexedDB

    (1)概述

    IndexedDB 提供了一個類似 NoSQL 的 key/value 資料庫,它可以儲存大量結構化數據,甚至是檔和 blob。每個域至少有 1GB 的可用空間,並且最多可以達到剩余磁盤空間的 60%。

    IndexedDB 於 2011 年首次實作,並於 2015 年 1 月成為 W3C 標準,它具有良好的瀏覽器支持:

    key/value 資料庫意味著儲存的所有數據都必須分配給一個 key。它將key 與 value 相關聯,key 用作該值的唯一識別元,這意味著可以使用該 key 跟蹤該值。如果套用需要不斷獲取數據,key/value 資料庫使用非常高效且緊湊的索引結構來快速可靠地透過 key 定位值。使用該 key,不僅可以檢索儲存的值,還可以刪除、更新和替換該值。

    在說 IndexedDB 之前,先來看一些相關術語:

  • 資料庫: 一個域可以建立任意數量的 IndexedDB 資料庫,只有同一域內的頁面才能存取資料庫。

  • object store :相關數據項的 key/value 儲存。它類似於 MongoDB 中的集合或關聯式資料庫中的表。

  • key :用於參照 object store 中每條記錄(值)的唯一名稱。它可以使用自動增量數位生成,也可以設定為記錄中的任何唯一值。

  • index :在 object store 中組織數據的另一種方式。搜尋查詢只能檢查 key 或 index。

  • schema:object store、key 和 index 的定義。

  • version :分配給 schema 的版本號(整數)。IndexedDB 提供自動版本控制,因此可以將資料庫更新到最新 schema。

  • 操作 :資料庫活動,例如建立、讀取、更新或刪除記錄。

  • (2)特點及使用場景

    indexedDB 特點如下:

  • 可以將任何 JavaScript 型別的數據儲存為鍵值對,例如物件(blob、檔)或陣列等。

  • IndexedDB API 是異步的,不會在數據載入時停止頁面的渲染。

  • 可以儲存結構化數據,例如 Date、視訊、影像物件等。

  • 支持資料庫事務和版本控制。

  • 可以儲存大量數據。

  • 可以在大量數據中快速定位/搜尋數據。

  • 資料庫是域專用的,因此任何其他站點都無法存取其他網站的 IndexedDB 儲存,這也稱為同源策略。

  • IndexedDB 使用場景:

  • 儲存使用者生成的內容: 例如表單,在填寫表單的過程中,使用者可以離開並稍後再回來完成表單,儲存之後就不會遺失初始輸入的數據。

  • 儲存套用狀態: 當使用者首次載入網站或套用時,可以使用 IndexedDB 儲存這些初始狀態。可以是登入身份驗證、API 請求或呈現 UI 之前所需的任何其他狀態。因此,當使用者下次存取該站點時,載入速度會增加,因為套用已經儲存了狀態,這意味著它可以更快地呈現 UI。

  • 對於離線工作的套用: 使用者可以在套用離線時編輯和添加數據。當應用程式來連線時,IndexedDB 將處理並清空同步佇列中的這些操作。

  • (3)IndexedDB 操作

    不同瀏覽器的 IndexedDB 可能使用不同的名稱。可以使用以下方法檢查 IndexedDB 支持:

    const indexedDB =
    window.indexedDB ||
    window.mozIndexedDB ||
    window.webkitIndexedDB ||
    window.msIndexedDB ||
    window.shimIndexedDB;
    if (!indexedDB) {
    console.log("不支持 IndexedDB");
    }

    可以使用 indexedDB.open() 來連線資料庫:

    const dbOpen = indexedDB.open('performance'1);

    indexedDB.open 的第一個參數是資料庫名稱,第二個參數是可選的版本整數。

    可以使用以下三個事件處理常式監聽 indexedDB 的連線狀態:

    ① onerror

    在無法建立 IndexedDB 連線時,將觸發該事件:

    // 連線失敗
    dbOpen.onerror = e => {
    reject(`IndexedDB error: ${ e.target.errorCode }`);
    };

    如果在無痕模式、私密模式下執行瀏覽器,可能不支持 IndexedDB,需要禁用這些模式。

    ② onupgradeneeded

    一旦資料庫連線開啟,就會觸發 onupgradeneeded 事件,該事件可用於建立 object store。

    dbOpen.onupgradeneeded = e => {
    const db = dbOpen.result;
    // 建立 object store
    const store = db.createObjectStore("cars", { keyPath"id" });
    // 使用自動遞增的id
    // const store = db.createObjectStore('cars', { autoIncrement: true }); 
    // 建立索引
    store.createIndex("cars_colour", ["colour"], { 
    uniquetrue
    }); 
    // 建立復合索引
    store.createIndex("colour_and_make", ["colour""make"], {
    uniquefalse,
    });
    };


    IndexedDB 使用了 object store 的概念,其本質上是數據集合的名稱。可以在單個資料庫中建立任意數量的 object store。keyPath是 IndexedDB 將用來辨識物件欄位名稱,通常是一個唯一的編號,也可以透過 autoIncrement: true 來自動為 store 設定唯一遞增的 ID。除了普通的索引,還可以建立復合索引,使用多個關鍵詞的組合進行查詢。

    ③ onsuccess

    在連線建立並且所有升級都完成時,將觸發該事件。上面我們已經新建了 schema,接下來就可以在onsuccess 中添加、查詢數據。

    // 連線成功
    dbOpen.onsuccess = () => {
    this.db = dbOpen.result;
    //1
    const transaction = db.transaction("cars""readwrite");
    //2
    const store = transaction.objectStore("cars");
    const colourIndex = store.index("cars_colour");
    const makeModelIndex = store.index("colour_and_make");
    //3
    store.put({ id1colour"Red"make"Toyota" });
    store.put({ id2colour"Red"make"Kia" });
    store.put({ id3colour"Blue"make"Honda" });
    store.put({ id4colour"Silver"make"Subaru" });
    //4
    const idQuery = store.get(4);
    const colourQuery = colourIndex.getAll(["Red"]);
    const colourMakeQuery = makeModelIndex.get(["Blue""Honda"]);
    // 5
    idQuery.onsuccess = function () {
    console.log('idQuery', idQuery.result);
    };
    colourQuery.onsuccess = function () {
    console.log('colourQuery', colourQuery.result);
    };
    colourMakeQuery.onsuccess = function () {
    console.log('colourMakeQuery', colourMakeQuery.result);
    };
    // 6
    transaction.oncomplete = function () {
    db.close();
    };
    };




    這裏總共有六部份:

    1. 為了對資料庫執行操作,我們必須建立一個 schema,一個 schema 可以是單個操作,也可以是多個必須全部成功的操作,否則都不會成功;

    2. 這裏用來獲取 cars object store 的參照以及對應的索引;

    3. object store 上的 put 方法用於將數據添加到資料庫中;

    4. 這裏就是數據的查詢,可以使用 keyPath 的值直接查詢計畫(第14行);第15行中的 getAll 方法將返回一個包含它找到的每個結果的陣列,我們正在根據 cars_colour 索引來搜尋 Red,應該會尋找到兩個結果。第16行根據復合索引尋找顏色為Blue,並且品牌為 Honda 的結果。

    5. 搜尋成功的事件處理常式,它們將在查詢完成時觸發。

    6. 最後,在事務完成時關閉與資料庫連線。無需使用 IndexedDB 手動觸發事務,它會自行執行。

    執行上面的程式碼,就會得到以下結果:

    可以在 Chrome Devtools 中檢視:

    下面來看看如何更新和刪除數據。

  • 更新: 首先使用個 get 來獲取需要更新的數據,然後使用 store 上的 put 方法更新現有數據。put 是一種「插入或更新」方法,它要麽覆蓋現有數據,要麽在新數據不存在時插入新數據。

  • const subaru = store.get(4);
    subaru.onsuccess= function () {
    subaru.result.colour = "Green";
    store.put(subaru.result);
    }

    這會將資料庫中 Silver 色的 Subaru 的顏色更新為綠色。

  • 刪除 :可以使用 delete API 來刪除數據,最簡單的方法是透過其 key 來刪除:

  • const deleteCar = store.delete(1);
    deleteCar.onsuccess = function () {
    console.log("Removed");
    };

    如果不知道 key 並且希望根據值來刪除,可以這樣:

    const redCarKey = colourIndex.getKey(["Red"]);
    redCarKey.onsuccess = function () {
    const deleteCar = store.delete(redCarKey.result);
    deleteCar.onsuccess = function () {
    console.log("Removed");
    };
    };

    結果如下:

    5. 儲存空間分析

    可以使用基於 Promise 的 Storage API 檢查 Web Storage、IndexedDB 和 Cache API 的剩余空間。異步 .estimate() 方法返回:

  • quota 內容:可用的空間;

  • usage 內容:已用的空間。

  • (async () => {
    if (!navigator.storage) return;
    const storage = await navigator.storage.estimate();
    console.log(`可用大小: ${ storage.quota / 1024 } Kb`);
    console.log(`已用大小: ${ storage.usage /
    1024 }
     Kb`
    );
    console.log(`已用占比: ${ Math.round((storage.usage / storage.quota) * 100) }%`);
    console.log(`剩余大小: ${ Math.floor((storage.quota - storage.usage) /
    1024) }
     Kb`
    );
    })();

    Storage API 的瀏覽器相容性如下: