Skip to main content

[JS30] Day15: LocalStorage and Event Delegation

這堂課我們要學習用 localStorage 儲存資料狀態,以及 event delegation 如何賦予新建立的元素工作。

HTML

有兩個 input,一個輸入文字,一個提交表單,我們要將提交的資訊放入.plates 裡面的<li>

<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<p></p>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items">
<input type="text" name="item" placeholder="Item Name" required />
<input type="submit" value="+ Add Item" />
</form>
</div>

JavaScript

選取元素

const addItems = document.querySelector(".add-items");
const itemsList = document.querySelector(".plates");

提交表單時要存入東西

在表單 submit 時,預設會進行重新整理,透過preventDefault擋住,儲存<input>輸入的內容在 itmes 內,要有 text 跟 done 兩個屬性。最後透過 reset 重置<input>

const items = [];

function addItem(e) {
e.preventDefault();
const text = this.querySelector("[name=item]").value;
const item = {
text: text,
done: false,
};
items.push(item);
this.reset();
}

addItems.addEventListener("submit", addItem);

HTMLFormElement.reset() @MDN

把東西放進清單之中

剛剛存入 items 內的東西,我們要放入清單之中,這邊將次序(i)存入每個<li>元素的data-index,方便之後的勾選。

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("");
}

勾選與否(event delegation)

由於我們一開始沒有任何<li>元素,所以我們要在他的母層使用監聽器,監聽典擊事件,如果該事件的對象剛好是<input/>元素,那我們就要透過他dataset裡面的 index,勾選與否對應 items[index]的 done 屬性,再透過populateList重新加東西放進清單之中。

function toggleDone(e) {
if (!e.target.matches("input")) return;
const el = e.target;
const index = el.dataset.index;
console.log(el.dataset.index);
items[index].done = !items[index].done;
populateList(items, itemsList);
}

itemsList.addEventListener("click", toggleDone);

localStorage 解決重新整理清單不見的問題

我們需要在資料有變化的時候將 items 物件存進 localStorage,一個是在提交表單時(addItem),一個是在修改勾選與否的時候(toggleDone)

localStorage.setItem("items", JSON.stringify(items));

透過setItem我們存入以下內容,可以透過檢查(F12)內的 application->storage->Local Storage 找到

而我們也要在 js 檔一開始透過getItem的方法拿回資料來顯示,並先執行一次populateList放入清單。

const items = JSON.parse(localStorage.getItem("items")) || [];
populateList(items, itemsList);

參考資料