iT邦幫忙

2021 iThome 鐵人賽

DAY 30
1
自我挑戰組

JavaScript老學徒筆記—馬步篇系列 第 35

最終章:Todo List實作

前面提到了物件、陣列、DOM元素的選取、事件監聽,以及最後的localStorage。這些足夠我們用JavaScript做一個小小的網頁程式,來驗證一下之前提到的方法。

這次我們要來做的是Todo List。

假設金庸先生要邀請武林高手來參加華山論劍,要邀請的人太多了,他記性不好,所以寫了一個小程式來記錄與會者名單。大概是長這個樣子。

然後在來拆解畫面上的功能:

我們可已先把上面的的那張圖區分為三種程式區塊:

  • 事件:
    • 加入邀請名單:點擊,使用者輸入的資料加入「邀請名單」的localStorage,並渲染到畫面
    • 寄出:將資料從「邀請名單」的localStorage中移除,加入已寄出名單的localStorage,並渲染到畫面
    • 移除:將資料由「已寄出名單」的localStorage中移除,並渲染到畫面
  • 資料:
    • 邀請名單的localStorage資料
    • 寄出名單的localStorage資料
  • 畫面:將localStorage的資料渲染到網頁

所以我們就可以開始實作了!

畫面上的HTML碼如下:

<div class="content">

  <div class="logo">
    <img src="https://imgur.com/uEvCO7p.png" width="150px" alt="">
    <div class="logotext">TODO LIST</div>
  </div>

  <div class="addList">
    <input type="text" size="30" class="text" placeholder="請輸入與會者姓名" required>
    <button type="button" class="send">新增邀請名單</button>
  </div>

</div>

<div class="item">
  <h3>計畫邀請<span class="noneNum"></span>人</h3>
  <ul class="list">

  </ul>
</div>

<div class="finishedItem">
  <h3>已邀請<span class="doneNum"></span>人</h3>
  <ul id="finishlist">

  </ul>
</div>

進入JavaScript的部分,先把DOM元素選取起來:

//指定DOM
let send = document.querySelector('.send');
let list = document.querySelector('.list');
let finishList = document.getElementById('finishlist');

接下來定義資料的部分:

  • 計畫邀請的名單,要把它變成陣列物件的格式
  • 已經寄出邀請函的名單,也要轉成陣列物件的格式
//資料:設定計畫邀請名單「listData」的localStorage資料,轉為陣列物件
let data = JSON.parse(localStorage.getItem('listData')) || [];

//資料:設定寄出名單「listFinish」的localStorage資料,轉為陣列物件
let finishData = JSON.parse(localStorage.getItem('listFinish')) || [];

接下來把事件綁訂到前面指定的DOM元素上。然後更新資料,此時尚未輸入資料,localStorage的key應該還沒建立,所以為空陣列。

//事件綁定,監聽與更新
send.addEventListener('click', addData);
list.addEventListener('click', toggleDone);
finishList.addEventListener('click', deleDone);

//更新畫面上的資料
updateList(data);
updateFinish(finishData);

按下「新增邀請名單後」把資料新增到data中,並叫用updateList這個函式,把資料組字串,渲染到畫面中。

//按下「新增邀請名單後」,把資料新增到data中,並叫用updateList
function addData(e) {
    var txt = document.querySelector('.text');
    if (txt.value == "") {
        alert('必須輸入與會者姓名');
        return;
    }
    var toInvite =
    {
        content: txt.value
    }

    data.push(toInvite);    
    updateList(data);
    localStorage.setItem('listData', JSON.stringify(data));
    txt.value = '';
}
//更新邀請清單
function updateList(items) {
    str = '';
    let len = items.length; 
		//for迴圈組字串   
    for (let i = 0; len > i; i++) {
        console.log(items[i])
        str += `<li><a href="#" data-index=${i}>移到已邀請</a><span>${items[i].content}</span></li>`;
    }
    list.innerHTML = str;
    let noneNum = document.querySelector('.noneNum');
    noneNum.textContent = len;
}

按下「移到已邀請」時,執行以下程式區塊:

//將與會者由邀請清單移至邀請函已寄出清單
function toggleDone(e){
		//避免事件冒泡
    e.preventDefault();
		//如果點選的不是a標籤,那就不往下執行
    if(e.target.nodeName !== 'A'){
        return;
    }
    let index = e.target.dataset.index;
		//把點選的資料推送到finishData中
    finishData.push(data[index]);
		//清除計畫邀請data中的資料
    data.splice(index,1);
		//更新計畫邀請的名單
    localStorage.setItem('listData',JSON.stringify(data));
		//渲染網頁
    updateList(data);
		//更新已寄出邀請函的名單
    localStorage.setItem('listFinish',JSON.stringify(finishData));
		//渲染網頁
    updateFinish(finishData);
}

然後是渲染「已邀請名單」的部分:

//更新已寄邀請函清單
function updateFinish(finishItems){
    let mailStr = '';
    let len = finishItems.length;
    console.log(finishItems);
    console.log(len);
		//for迴圈組字串 
    for(let i=0;i<len; i++){
        console.log(finishItems[i]);
        mailStr+= `<li><a href="#" data-num=${i}>移除</a><span>${finishItems[i].content}</span></li>`
    }
    finishList.innerHTML = mailStr;
    var doneNum = document.querySelector('.doneNum');
    doneNum.textContent = len;
}

如果點選「刪除」,執行以下程式:

//刪除已邀請的貴賓
function deleDone(e){
    e.preventDefault();
    if(e.target.nodeName !== 'A'){
        return;
    }
    let num = e.target.num;
		//清除計畫邀請data中的資料
    finishData.splice(num,1);
		//更新已寄出邀請函的名單
    localStorage.setItem('listFinish',JSON.stringify(finishData));
		//渲染到網頁
    updateFinish(finishData);
}

來看看我的實作吧!

https://codepen.io/popeye_ux/pen/KKqbMwq


上一篇
好記性的瀏覽器:localStorage
系列文
JavaScript老學徒筆記—馬步篇35

尚未有邦友留言

立即登入留言