# 認識瀏覽器的儲存空間-localStorage ![](https://i.imgur.com/t8vbS3y.jpg) ### :gem:何謂localStorage localStorage是由html5所提供的一個web storage,有下列幾項特點: * 無法[跨域](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/CORS)使用,與cookie一樣只認domain name * 達到5MB的儲存數據空間可以使用來降低request數量 * 用來儲存一些不重要但卻影響著效能等等的資訊。 --- ### :gem:關於localStorage、sessionStorage、cookie 差異 | 項目 | localStorage | sessionStorage | Cookie | | ---------------- | -------------------------------------------- | -------------------- | ------------------------------------ | | 儲存數據 | 可以達到 5M 或更大 | 可以達到 5M 或更大 | 不能超過4k | | 生命週期 | 瀏覽器關閉後資料不會移除,除非用戶端清除資料 | 刷新頁面資料依舊存在,關閉瀏覽器後資料移除 | 在後端設置的cookie過期時間內都會有效 | | 傳遞資料到Server | 否 | 否 | 是 | --- ### :pencil:localStorage 簡單練習 #### <font color=#FF6600>**PART1**</font> 最近在工作實作上遇到下面的情境:speech_balloon: (待補) 想到的兩種解法是 1.判斷是否打過API 2.使用localStorage儲存數據 最後我選擇用localStorage實作 透過這兩種方式來記住使用者是否曾經點擊過此按鈕, 若已點擊過A按鈕,就算重整頁面B按鈕也會是取消禁用的狀態 #### :bulb:知識點 **localStorage** 1. `localStorage.setItem('key','value')`:透過setItem指定物件屬性的`key`跟`value` 2. `locaStorage.getItem('key')`:透過getItem方法屬性中`key`,可以得到屬性中對應的`value` **Event** 1. [target.addEventListener](https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener) > html ``` <div> <ul> <li style="margin-left:45px; list-style-type:none"> <button type="button" class="download">A</button> </li> <li style="margin-left:45px; list-style-type:none"> <button type="button" class="download" disabled="disable">B</button> </li> </ul> </div> ``` > javascript ``` let csrBtn = document.querySelector(".download"); function saveBtnClick() { localStorage.setItem("setValue", 1); //儲存到localStorage 記錄使用者是否點擊過 } csrBtn.addEventListener("click", saveBtnClick); let str = localStorage.getItem("setValue"); //透過屬性的中的key,得到對應的value if (str == 1) { $("#touchBtn").removeAttr("disabled"); } ``` #### <font color=#FF6600>**PART2**</font> [JavaScript30-NO.15 ](https://github.com/soyaine/JavaScript30) 透過localStorage的作法做資料的新增刪除。 #### :bulb:知識點 **Event** 1. event.preventDefault 2. [event.addEventListener](https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener) **localStorage** 1. `localStorage.setItem('key','value')` 2. `locaStorage.getItem('key')` **JSON** 1. `JSON.stringify()` 2. `JSON.parse()` **作法:** :one:取得form元素,並宣告一個空陣列準備放入資料。 > javascript ``` const addItems = document.querySelector('.add-items'); const itemsList = document.querySelector('.plates'); var items = []; ``` :two:寫一個addItem函式,選取form中輸入框欄位值 ``` function addItem(e) { e.preventDefault(); //避免每新增一筆資料時就重整一次頁面 const text = this.querySelector('[name=item]').value; const item = { text: text, //要放入的清單 done: false //是否勾選 } items.push(item); this.reset(); ..... } ``` :three:顯示新增清單 ``` function populateList(plates = [], plateslist) { //新增列表 plateslist.innerHTML = plates.map((plate, i) => { return ` <li> <input type="checkbox" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} > <label for="item${i}">${plate.text}</label> </li> `; }).join(''); } ``` * [ES6寫法在函式中給予參數的地方放入預設值](https://pjchender.blogspot.com/2017/01/es6-default-value.html) * 使用map將所有陣列中的元素依序分別傳入一次至 callback 函式當中,並以此回呼函式每一次被呼叫的回傳值來建構一個新的陣列 * 使用`join`將陣列所有元素連結,合併成一個字串。 :four: 再回到addItem函式把[key,value]寫入localStorage ``` function addItem(e) { ..... populateList(items, itemsList); //輸入送出後重新列出物件字串 localStorage.setItem('items', JSON.stringify(items)); ..... } ``` 將items(自定義)存入localStorage中,因localStorage值是字串,需透過JSON.stringify將 物件或陣列轉為字串。 若沒轉為字串,新增資料時會得到下面的結果 ![](https://i.imgur.com/mSv3I5m.png) :five:儲存checkbox狀態 ``` function toggleDone(e) { //check if (!e.target.matches('input')) return; //點擊的位置是否是input const el = e.target; const index = el.dataset.index; //取得checkbox位置 items[index].done = !items[index].done; //checkbox true or false populateList(items, itemsList); //更新數據 localStorage.setItem('items', JSON.stringify(items)); //更新後的狀態寫入localStorage } addItems.addEventListener('submit', addItem); itemsList.addEventListener('click', toggleDone); populateList(items, itemsList); ``` :six: 新增刪除、選取所有checkbox、取消所有checkbox ``` const checkAllBtn = document.querySelector('.check-all'); const unCheckAllBtn = document.querySelector('.uncheck-all'); const deleteAllBtn = document.querySelector('.delete-all'); ``` ``` checkAllBtn.addEventListener('click', () => { //透過迴圈遍歷每個item將checkbox狀態改為勾選 items.forEach(item => { item.done = true; }); populateList(items, itemsList); //更新數據 localStorage.setItem('items', JSON.stringify(items)); }); unCheckAllBtn.addEventListener('click', () => { //遍歷迴圈的每個item將checkbox狀態改為取消勾選 items.forEach(item => { item.done = false; }); populateList(items, itemsList);//更新數據 localStorage.setItem('items', JSON.stringify(items)); }); deleteAllBtn.addEventListener('click', () => { items = []; //將一開始宣告的陣列設為空值 populateList(items, itemsList);//更新數據 localStorage.setItem('items', JSON.stringify(items)); }); ``` DEMO:[https://evalin0316.github.io/localStorage/localStorage.html](https://evalin0316.github.io/localStorage/localStorage.html) > 參考資料: >* http://techaride.blogspot.com/2012/07/javascript-localstorage.html >* https://github.com/FEGuideTeam/FEGuide/tree/master/html%E9%97%AE%E9%A2%98