Anthony Chao

JS30 day15 Local Storage and Event delegation

#Javascript

JS30 day15 - JS30 day15 Local Storage and Event delegation

作業內容

今天的內容在講說如何使用 Local Storage 還有如果要指定監聽的對象是動態變化的應該怎麼處理,網頁的部分是透過一個菜單來實作

學到什麼

  • JS
    1. preventDefault() 參考資料:https://ithelp.ithome.com.tw/articles/10198999
    2. 使用屬性來當作選擇器 this.querySelector('[name=item]')
    <input type="text" name="item" placeholder="Item Name" required="">
    1. 使用 this.reset(); 重置表單
    2. 在標籤裡面動態插入 <li>標籤:
    function populateList(plates = [], plateList){
      plateList.innerHTML = plates.map((plate, i) => {
        return `
          <li>
            <label for="">${plate.text}</label>
          </li>
        `
      }).join("");
    }
    1. 在 html 裡面,如果有一個 checkbox 的 input 以下三種狀況都還是會讓他呈現 checked:true 的狀態
    <input type="checkbox" checked>
    <input type="checkbox" checked="qq">
    <input type="checkbox" checked=false>
    所以如果要根據屬性不同做出不同的 checked 狀態,只能加入 checked 或是空白字元
    //寫在 js 裡面
    <input type="checkbox" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''}>
    1. localStorage 是個可以把資料儲存在瀏覽器的空間,不過要記得只能存字串
    localStorage.setItem("items", items) //第一個參數是 key 的名字,第二個參數是要存的東西
    localStorage.getItem()
    localStorage.removeItem()
    而一開始的 items 就可以改為先試著從 localStorage 抓資料,沒有的話才給空陣列
    const items = JSON.parse(localStorage.getItem('items')) || [];
    1. 我們要去捕捉每一個新長出來的 list 去監聽事件,對這種動態元素,最好的方式是去用他的父元素監聽,利用冒泡機制,所以父元素也會監聽到
    function toggleDone(e){
      console.log(e.target)
    }
    itemsList.addEventListener('click', toggleDone)
    但這樣會產生另一個問題,從 console log 可以看到每次都會出現兩個事件,所以必須再去濾除條件
    function toggleDone(e){
    if(!e.target.matches('input')) return;
    }

參考資料: https://github.com/wesbos/JavaScript30

code 內容:

HTML:

<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>

CSS:

html {
  box-sizing: border-box;
  background: url('http://wes.io/hx9M/oh-la-la.jpg') center no-repeat;
  background-size: cover;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  font-family: Futura,"Trebuchet MS",Arial,sans-serif;
}

*, *:before, *:after {
  box-sizing: inherit; 
}

svg {
  fill:white;
  background: rgba(0,0,0,0.1);
  padding: 20px;
  border-radius: 50%;
  width: 200px;
  margin-bottom: 50px;
}

.wrapper {
  padding: 20px;
  max-width: 350px;
  background: rgba(255,255,255,0.95);
  box-shadow: 0 0 0 10px rgba(0,0,0,0.1);
}

h2 {
  text-align: center;
  margin: 0;
  font-weight: 200;
}

.plates {
  margin: 0;
  padding: 0;
  text-align: left;
  list-style: none;
}

.plates li {
  border-bottom: 1px solid rgba(0,0,0,0.2);
  padding: 10px 0;
  font-weight: 100;
  display: flex;
}

.plates label {
  flex: 1;
  cursor: pointer;
}

.plates input {
  display: none;
}

.plates input + label:before {
  content: '⬜️';
  margin-right: 10px;
}

.plates input:checked + label:before {
  content: '🌮';
}

.add-items {
  margin-top: 20px;
}

.add-items input {
  padding: 10px;
  outline: 0;
  border: 1px solid rgba(0,0,0,0.1);
}

JS:

const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const items = JSON.parse(localStorage.getItem('items')) || [];

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

function populateList(plates = [], plateList){
  plateList.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("");
}

function toggleDone(e){
  if(!e.target.matches('input')) return;
  const el = e.target;
  const index = el.dataset.index;
  items[index].done = !items[index].done
  localStorage.setItem("items", JSON.stringify(items))
}

addItems.addEventListener('submit', addItem)
itemsList.addEventListener('click', toggleDone)
populateList(items, itemsList) // 上面那一列是表單送出才會發生作用,這一列是重新整理或者重新進到這個網頁都會發生作用