1. 程式人生 > >一篇文章圖文並茂地帶你輕鬆學會 HTML5 storage

一篇文章圖文並茂地帶你輕鬆學會 HTML5 storage

## html5 storage api `localStorage` 和 `sessionStorage` 是 `html5` 新增的用來儲存資料的物件,他們讓我們可以以鍵值對的形式儲存資訊。 ### 為什麼要有 `storage` ? 我們已經有了 `session` 可以幫助我們儲存資訊,為何還需要 `storage` 呢? 1. 各個瀏覽器的 `cookie` 長度大概只能在 `4kb` 左右,而 `storage` 大概能達到 `5M`,這意味著可以儲存更多的資訊 2. `cookie` 可以被後端更改,在每次進行網路請求的時候都會被髮送給伺服器,而 `storage` 不會,這意味著這個儲存是完全受控於前端(JavaScript)的。 ### storage 型別 `storage` 一共有兩種 1. `localStorage` 這個儲存物件的儲存和 `origin` 有關,即只要是同域名同協議同埠,儲存是共享的。儘管關機了,或是關掉瀏覽器了,只要開啟同源網站,儲存的資料會依然存在,資料不會過期消失。 2. `sessionStorage` 這個儲存物件的儲存是暫時的,只保持在當前會話中,簡單來說就是和瀏覽器的一個 `tab` 有關,只要 `tab` 關掉了再開啟資料就沒了,但是在當前介面重新整理的話,資料就還在(這個時候認為是一個 `tab`)。 兩個 `storage` 的 `api` 很相似,下面以 `localStorage` 為例 ### localStorage 演示 #### 基礎 `api` ```js localStorage.setItem("name", "huro"); // 設定鍵值對 ``` ![](https://img2020.cnblogs.com/blog/2286610/202102/2286610-20210213185656582-617272945.png) 可以在 `chrome` 瀏覽器的控制檯進行觀察,這裡已經設定上去了。下面也可以做相應的測試。 ```js localStorage.getItem("name"); // huro localStorage.removeItem("name"); // 刪除某個鍵 localStorage.clear(); // 刪除所有鍵值對 localStorage.key(0); // 獲得索引為 0 的key localStorage.length; // 獲得 `localStroage` 的鍵的個數 ``` 以上是 `storage` 的 `api` 唯一需要注意的是 `key(index)` 這個 `api` 和 `key` 被設定的先後是沒有關係的。 #### 類物件操作 也可以用類物件的方法操作 ```js localStorage.name = "huro"; console.log(localStorage.name); // huro delete localStorage.name; // 刪除鍵 ``` 但是上面的做法不推薦,如果用的是某些特殊的 `key` 例如 `length` 就會報錯,因為原先 `localStorage.length` 表示獲得鍵值對長度,理應是不能修改的。 ```js localStorage["length"] = 4; // 修改無效 ``` 因此不推薦用這個做法修改 `storage` #### 遍歷鍵值 由於 `storage` 並沒有 `Symbol.iterator` 屬性,這意味著 `storage` 不能用 `for of`迴圈遍歷。以下有三種遍歷方式。 假設我們只有一個鍵值對 `name: huro` 1. `for in` 迴圈 ```js for (let key in localStorage) { console.log(key); } ``` ![](https://img2020.cnblogs.com/blog/2286610/202102/2286610-20210213185643701-1211698067.png) 上述的寫法是錯誤的,因為 `for in` 迴圈會遍歷原型鏈上的屬性和方法,因此需要稍作改善。 ```js for (let key in localStorage) { if (!localStorage.hasOwnProperty(key)) { continue; } console.log(key); } ``` 這個時候就能正確的只打印出鍵 `name` 2. 簡單 `for` 迴圈 ```js for(let i = 0; i < localStorage.length; i+= 1) { let key = localStorage.key(i); console.log(key); } ``` 這個時候能正確的只打印出鍵 `name` 3. `Object.keys()` 這個方法會獲得某個物件自身的 `key`,而不會管原型鏈上的 ```js const keys = Object.keys(localStorage); for(let key of keys) { alert(key); } ``` 而且獲得的 `key` 是陣列,具有 `iterator` 因此可以用 `for of` 遍歷 這個時候能正確的只打印出鍵 `name` #### 只能是 `string` `storage` 被設計出來比較不足的地方是,鍵和值都只能是 `string` 型別的,如果不是的話,會自動轉換成 `string`。 由於是隱式轉換,初學者往往不知道,這意味著可能帶來一些 `bug` ```js localStorage.user = { name: "huro" }; console.log(localStorage.user); // [object Object] ``` 上述程式碼在儲存 `user` 的時候,被自動呼叫 `toString` 方法,轉化為了 `[object Object]` #### `storage` 事件 `storage` 事件返回一個物件,裡面包含幾個引數 1. `key` 改變的鍵 2. `oldValue` => `舊值 || null` 3. `newValue` => `新值 || null` 4. `url` 觸發這個事件的 `url` 地址 5. `storageArea` 要麼是 `localStorage` 要麼是 `sessionStorage` 取決與是更改哪個`storage`的 ```js // 1.html window.addEventListener("storage", (state) => { console.log(state.key, state.value, state.url); // name huro ./2.html(實際 url 是絕對路徑) }) // 2.html localStorage.setItem("name", "huro"); ``` 還記得我們之前說過, `localStorage` 只要是同源都可以分享嗎,這意味如果我們打開了兩個視窗,只要他們是同源的,我們可以用上述的監聽事件,監聽另一個埠修改 `storage`,也就是可以實現不同的視窗之間的資料共享。 注意: 經測試,`chrome` `edge` 等現代瀏覽器不會觸發自身檔案或同文件的 `storage` 事件,即必須是兩個不同的 `html` 才會互相觸發。 例如 `test1.html` 和 `test2.html` 都設定了 `storage` 監聽事件,且同源。 則 `test1.html` 的 `storage` 的 `api` 事件會觸發 `test2.html` 的,但是不能觸發本身的 `storage` 監聽事件。 另外這裡的 `api` 事件也有限制,經過筆者測試,似乎只有 1. `setItem` 2. `getItem` 3. `removeItem` 有效果,而 `clear` 事件是沒有效果的。 上面全程用 `localStorage` 演示, `sessionStorage` 也是類似的,讀者有興趣可以自行碼一下程式碼。 ### 總結 `storage` 是很好的一個 `html5` 特性,讓我們方便快捷的儲存資料,美中不足的是隻能儲存字元型資料,不過也很容易解決這個問題。同時利用監聽事件,也可以實現不同視窗之間的廣播機制。是非常實用的一個