今天來嘗試做個簡單版的 To-do List,讓自己對於 To-do List 的實作有一個粗略的概念,以下會先敘述實作流程,再一步步完成。
那就開始囉~
因為主要功能包含新增,刪除和勾選完成,區域又分成待辦事項區和已完成事項區,所以上篇會先針對待辦事項區的功能實作,下篇再繼續實作已完成事項區的功能。
// 整個待辦事項表單
<div class="todo">
// 1. 可以輸入事項的區域
<header>
<h4>待辦事項</h4>
<div class="form">
<input type="text" placeholder="add todos" class="newTodo">
<button class="btn addButton">新增</button>
</div>
</header>
// 2. 顯示待辦事項的區域
<ul class="pending">
<!-- 放待辦事項新增區域 -->
</ul>
// 3. 顯示已完成事項的區域
<h4>完成事項</h4>
<ul class="done">
<!-- 放完成事項區域 -->
</ul>
</div>
以下是會需要監聽的元素,先用querySelector()
方法選出來並存到變數中
// 選取元素
let pending = document.querySelector('.pending') // 會放入使用者輸入內容的容器
let addButton = document.querySelector('.addButton') // 新增按鈕
let input = document.querySelector('.newTodo') //輸入框
let done = document.querySelector('.done') // 完成區域
對於節點的新增、刪除還沒有概念的朋友推薦先看看這篇 走!去瀏覽器用 create & append 加餐,有超級可愛的餅乾怪,看完保證一定學會節點的操作~~~
li
的元素appendChild()
方法,將節點加入到容器pending
的末端function addTodo (text) {
const newTodo = document.createElement('li')
newTodo.innerHTML = `
<input value ="${text}">
<div class="icon-group">
<i class="delete fa fa-trash"></i>
<i class="check fa fa-check-circle"></i>
</div>
`
pending.appendChild(newTodo)
}
addTodo
函式中,就會新增一筆待辦事項addButton.addEventListener("click", function () {
const inputValue = input.value
if (inputValue.trim().length > 0) {
addTodo(inputValue)
}
})
為了確認addTodo
的函式能正常運作,可以先用假資料試試看~
這部分確認成功就可以刪除,如果要一開始顯示預設的資料可以保留沒關係
const todos = ['寫今天的鐵人賽文章', '寫明天的鐵人賽文章', '寫後天的鐵人賽文章']
function displayDummyData(todos) {
for (let todo of todos) {
addTodo(todo)
}
}
displayDummyData(todos);
由於我覺得勾選完成和刪除的行為是狀態的改變(可能是從未完成到已完成,或是被使用者刪除,感覺有點像Promise XD),所以用一個changeState
的函式封裝
closest()
向上找到li
元素
closest()
裡頭的參數放CSS選取器,會向上一直往根節點查找指定的元素,如果找到根節點都沒有指定的元素,則傳回 null值
li
放入已完成區域pending
aka 待辦事項區綁定監聽器,如果觸發就執行changeState
函式
function changeState (e) {
const list = e.target.closest('li')
if (e.target.classList.contains('delete')) {
list.remove();
}
else if (e.target.classList.contains('check')) {
list.remove()
const itemDone = document.createElement('li')
const content = list.children[0].value
itemDone.innerHTML += `<input value ="${content}" class="checked" disabled="disabled">
<div class="icon-group">
<i class="delete fa fa-trash"></i>
<i class="check fa fa-check-circle"></i>
</div>`
done.appendChild(itemDone)
}
}
pending.addEventListener('click', changeState)
在實作過程中體會到對於節點位置的關係越清晰才不會一直選錯節點,如果發生鬼打牆現象建議直接console.log()
,看看自己是不是明明想選蘋果卻選到奇異果
明天再來實作已完成事項區的部分囉~
參考資料:
實作一個簡單的 Todolist (上)
MDN - Element.children
JavaScript大全