目錄
一、功能需求
二、 HTML
三、CSS
四、js
1、綁定事件與初始設置
2.、綁定事項?
(1)添加操作:
(2)完成操作
(3)刪除操作
(4)修改操作
3、完整js代碼
總結與感悟
????????實現了一個包括 添加、完成、刪除、修改 等操作的 To-Do List,涵蓋了常見的 DOM 操作及事件綁定。目的為了掌握 JavaScript 操作 DOM 的技巧,項目還可用于實際開發中的簡單任務管理工具。
一、功能需求
-
添加待辦事項
- 用戶輸入內容后,點擊 "添加" 按鈕,將事項添加到列表中。
- 如果輸入為空,提示用戶輸入內容。
-
標記完成
- 點擊 "完成" 按鈕,可以標記當前事項為完成或取消完成。
-
刪除事項
- 僅當事項已標記完成時才能刪除。
-
修改事項
- 點擊 "修改" 按鈕,將事項內容回填到輸入框,用戶可以修改內容并保存。
二、 HTML
HTML 文件定義了一個簡單的頁面布局,包括輸入框、按鈕和一個表格來顯示待辦事項。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>待辦事項列表</title><link rel="stylesheet" href="css/todolist.css"><script src="js/todolist.js" defer></script>
</head><body><div class="container"><div class="top"><input type="text" class="content"><input type="button" value="添加" class="btn"></div><table border="1"><thead><tr><th>內容</th><th>操作</th></tr></thead><tbody><!-- 動態生成內容 --></tbody></table></div>
</body></html>
三、CSS
通過簡單的 CSS,提升待辦事項列表的外觀效果。
.container {width: 600px;margin: 0 auto;text-align: center;
}.top {margin-bottom: 20px;
}.content {width: 400px;padding: 5px;
}.btn {padding: 5px 10px;background-color: #007BFF;color: #fff;border: none;cursor: pointer;
}.btn:hover {background-color: #0056b3;
}table {width: 100%;border-collapse: collapse;
}td {padding: 10px;text-align: center;
}
最終:?
四、js
1、綁定事件與初始設置
首先獲取頁面中的按鈕、輸入框和表格的 tbody
元素
// 獲取添加按鈕
var btn = document.querySelector('.btn')
// 獲取輸入框
var content = document.querySelector('.content')
// 獲取tbody
var tbody = document.querySelector('tbody')
2.、綁定事項?
(1)添加操作:
用戶輸入內容后,點擊 "添加" 按鈕,內容將被添加到表格中。
第一版:
// 給添加按鈕綁事件
btn.onclick = function() {var text = content.valueconsole.log(text)// 創建元素td1 td2var tr = document.createElement('tr')var td1 = document.createElement('td')td1.innerText = textvar td2 = document.createElement('td')td2.innerHTML = '<input type="button" value="完成" class="finish"><input type="button" value="刪除" class="delete"><input type="button" value="修改" class="update"></input>'tr.append(td1)tr.append(td2)tbody.append(tr)}
?第二版:校驗輸入值,如果輸入框為空,仍會生成一個空白行,不是預期的行為。添加條件判斷語句
// 給添加按鈕綁事件
btn.onclick = function() {var text = content.valueif(text.length!= 0){console.log(text)// 創建元素td1 td2var tr = document.createElement('tr')var td1 = document.createElement('td')td1.innerText = textvar td2 = document.createElement('td')td2.innerHTML = '<input type="button" value="完成" class="finish"><input type="button" value="刪除" class="delete"><input type="button" value="修改" class="update"></input>'tr.append(td1)tr.append(td2)tbody.append(tr)// console.log('td1')// console.log('td2')// console.log('tr')}else{alert("請輸入信息!!!")}
}
? ? ? ? ? ? ? ? ? ??
第三版:但是!!這樣你輸入空格的時候也會產生空白行,于是添加
解決方法:var text = content.value.trim(); // 去掉輸入值的前后空格
? ? ? ? 并且優化每次輸入完成自動去掉輸入框中的值:在最后 補上content.value=''
????????
/*添加按鈕綁事件*/var text = content.value.trim(); // 去掉輸入值的前后空格if(text.length!= 0){console.log(text)// 創建元素td1 td2var tr = document.createElement('tr')var td1 = document.createElement('td')td1.innerText = textvar td2 = document.createElement('td')td2.innerHTML = '<input type="button" value="完成" class="finish"><input type="button" value="刪除" class="delete"><input type="button" value="修改" class="update"></input>'tr.append(td1)tr.append(td2)tbody.append(tr)content.value=''// console.log('td1')// console.log('td2')// console.log('tr')}else{alert("請輸入信息!!!")}
? ? ? ? ? ? ? ? ? ? ? ??
(2)完成操作
點擊 "完成" 按鈕,可以標記事項完成或取消完成。?
第一版:
/*給完成按鈕綁事件,這里注意要寫到添加按鈕里面,可以實時獲取最新的事件*/var finish = document.getElementsByClassName('finish')//循環給每一個按鈕綁事件for(var i = 0;i<finish.length;i++){finish[i].onclick = function() { //觸發事件時才執行var target = this.parentNode.previousElementSiblingtarget.style.textDecoration = 'line-through'}}
第二版:完成后只是簡單的給內容添加了劃線,在這里優化添加恢復操作【主要是判斷語句來實現】和一些其他樣式
/*給完成按鈕綁事件,這里注意要寫到添加按鈕里面,可以實時獲取最新的事件,同理其他按鈕也是這樣*/var finish = document.getElementsByClassName('finish')//循環給每一個按鈕綁事件for(var i = 0;i<finish.length;i++){finish[i].onclick = function() { //觸發事件時才執行var target = this.parentNode.previousElementSiblingif(target.style.textDecoration == 'line-through'){target.style.textDecoration = 'none'target.style.color= '#000'this.value = "完成"this.style.borderColor = '#910000'this.style.color='#910000'}else{target.style.textDecoration = 'line-through'target.style.color= '#888'this.value = "恢復"this.style.borderColor = '#888'this.style.color='#888'}}}
?
(3)刪除操作
?第一版:基本的刪除操作【關鍵代碼】
/*獲取刪除按鈕 */var deleteBtn = document.getElementsByClassName('delete')//循環綁事件for(var i=0;i<deleteBtn.length;i++){deleteBtn[i].onclick.function () {// 刪除整行,找到tbody--刪除trvar target = this.parentNode.parentNodetbody.removeChild(target)}}
第二版:修改細節,必須完成了才能刪除【要結合完成操作】
/*獲取刪除按鈕*/var deleteBtn = document.getElementsByClassName('delete')//循環綁事件for(var i = 0;i < deleteBtn.length;i++){deleteBtn[i].onclick =function(){if(this.parentNode.previousElementSibling.style.textDecoration=="line-through"){// 刪除整行,找到tbody--刪除trif(confirm("確定要刪除嗎?")){ //用戶點擊確定時就會返回true var target = this.parentNode.parentNodetbody.removeChild(target)}}else{alert("努力完成吧ヾ(?°?°?)ノ゙")}}}
(4)修改操作
點擊 "修改" 按鈕,將事項內容回填到輸入框,用戶可以編輯后保存。
????????這里稍微復雜一點,需要注意對添加操作的重寫,全局變量 flag 、targetFlag的使用,從而獲得需要修改的是存儲的是哪個信息
/*獲取修改按鈕--回寫:讓內容重新回到輸入框,進行修改*/var update = document.getElementsByClassName('update')//循環綁事件for(var i=0;i<update.length;i++){update[i].onclick = function(){//找到td--》tdvar target = this.parentNode.previousElementSiblingif(target.style.textDecoration=="line-through"){//事項已經完成無需修改alert("已經完成啦無需修改~~")btn.value="添加" //這里需要在最外層循環進行判斷,否則會是無腦的執行添加操作}else{content.value = target.innerText btn.value="修改"targetFlag = target.getAttribute("index")}}}
添加全局變量來獲取要修改哪條信息
//定義標識
var flag = 1
//存儲修改的是哪條信息
var targetFlag = 0
重新添加操作:加上?td1.setAttribute("index",flag)? ?flag++來存儲信息索引。
/*添加按鈕綁事件*/var text = content.value.trim(); // 去掉輸入值的前后空格if(text.length!= 0){console.log(text)// 創建元素td1 td2var tr = document.createElement('tr')var td1 = document.createElement('td')td1.setAttribute("index",flag)flag++td1.innerText = textvar td2 = document.createElement('td')td2.innerHTML = '<input type="button" value="完成" class="finish"><input type="button" value="刪除" class="delete"><input type="button" value="修改" class="update"></input>'tr.append(td1)tr.append(td2)tbody.append(tr)content.value=''// console.log('td1')// console.log('td2')// console.log('tr')}else{alert("請輸入信息!!!")}
?最后在添加操作之前進行判斷【return關鍵字的使用,判斷是修改還是添加】,并完成修改的操作
if(btn.value =="修改"){ //獲取所有內容 tbody--》tr-->td里面的第一個td(存儲內容的,用到偽類選擇器)var tds = document.querySelectorAll('tbody tr td:nth-child(1)')for(var i=0;i<tds.length;i++){if(tds[i].getAttribute('index') == targetFlag){ //與循環到的索引值相等 就修改tds[i].innerText = content.value //--->修改的關鍵語句//修改完成的善后處理content.value=''btn.value="添加"}}return }
?3
3、完整js代碼
// 獲取添加按鈕
var btn = document.querySelector('.btn')
// 獲取輸入框
var content = document.querySelector('.content')
// 獲取tbody
var tbody = document.querySelector('tbody')
//定義標識
var flag = 1
//存儲修改的是哪條信息
var targetFlag = 0/*給添加按鈕綁事件*/
btn.onclick = function() {if(btn.value =="修改"){ //獲取所有內容 tbody--》tr-->td里面的第一個td(存儲內容的,用到偽類選擇器)var tds = document.querySelectorAll('tbody tr td:nth-child(1)')for(var i=0;i<tds.length;i++){if(tds[i].getAttribute('index') == targetFlag){ //與循環到的索引值相等 就修改tds[i].innerText = content.value //--->修改的關鍵語句//修改完成的善后處理content.value=''btn.value="添加"}}return }/*添加按鈕綁事件*/var text = content.value.trim(); // 去掉輸入值的前后空格if(text.length!= 0){console.log(text)// 創建元素td1 td2var tr = document.createElement('tr')var td1 = document.createElement('td')td1.setAttribute("index",flag)flag++td1.innerText = textvar td2 = document.createElement('td')td2.innerHTML = '<input type="button" value="完成" class="finish"><input type="button" value="刪除" class="delete"><input type="button" value="修改" class="update"></input>'tr.append(td1)tr.append(td2)tbody.append(tr)content.value=''// console.log('td1')// console.log('td2')// console.log('tr')}else{alert("請輸入信息!!!")}/*給完成按鈕綁事件,這里注意要寫到添加按鈕里面,可以實時獲取最新的事件,同理其他按鈕也是這樣*/var finish = document.getElementsByClassName('finish')//循環給每一個按鈕綁事件for(var i = 0;i<finish.length;i++){finish[i].onclick = function() { //觸發事件時才執行var target = this.parentNode.previousElementSiblingif(target.style.textDecoration == 'line-through'){target.style.textDecoration = 'none'target.style.color= '#000'this.value = "完成"this.style.borderColor = '#910000'this.style.color='#910000'}else{target.style.textDecoration = 'line-through'target.style.color= '#888'this.value = "恢復"this.style.borderColor = '#888'this.style.color='#888'}}}/*獲取刪除按鈕*/var deleteBtn = document.getElementsByClassName('delete')//循環綁事件for(var i = 0;i < deleteBtn.length;i++){deleteBtn[i].onclick =function(){if(this.parentNode.previousElementSibling.style.textDecoration=="line-through"){// 刪除整行,找到tbody--刪除trif(confirm("確定要刪除嗎?")){ //用戶點擊確定時就會返回true var target = this.parentNode.parentNodetbody.removeChild(target)}}else{alert("努力完成吧ヾ(?°?°?)ノ゙")}}}/*獲取修改按鈕--回寫:讓內容重新回到輸入框,進行修改*/var update = document.getElementsByClassName('update')//循環綁事件for(var i=0;i<update.length;i++){update[i].onclick = function(){//找到td--》tdvar target = this.parentNode.previousElementSiblingif(target.style.textDecoration=="line-through"){//事項已經完成無需修改alert("已經完成啦無需修改~~")btn.value="添加" //這里需要在最外層循環進行判斷,否則會是無腦的執行添加操作}else{content.value = target.innerText btn.value="修改"targetFlag = target.getAttribute("index")}}}}
console.log(btn)
總結與感悟
? js語法很簡單,編寫代碼的時候最主要的還是思路。需要注意的和之前沒有見過知識點如下:
1、完成、刪除、修改的綁定操作都是基于添加操作的,因此他們都是在btn.onclick = function()下的,這樣可以實時獲取最新的事件并進行操作的綁定。
2、outline: none
—— 去除外輪廓,在本demo中用于表單元素的美化,按鈕的點擊的時候單元格不會有輪廓的變化
3、min-width
—— 最小寬度:在本demo中用于確保布局中某些元素在內容不足時也能保持穩定的寬度。比如當我們縮小windows時候表格會保持min_width不會被壓縮。
4、border-radius
—— 設置圓角。之前沒有詳細了解過,用于設置元素的邊框圓角,可實現按鈕、圖片等元素的圓角或圓形效果。可以分別指定 左上角、右上角、右下角 和 左下角 的圓角半徑
5、border-collapse
—— 表格單元格邊框合并:指定是否將表格的單元格邊框合并為一個。
separate
:單元格的邊框獨立存在(默認值)。collapse
:單元格的邊框合并為一個。
6、cursor
—— 鼠標樣式:設置鼠標指針懸停在元素上的樣式。
pointer
:小手樣式(常用于超鏈接或按鈕)。default
:默認箭頭樣式。text
:文本光標(用于文本選擇)。
7、trim()
方法 —— 去掉字符串前后空格,demo中用于優化添加操作輸入空格時的處理
8、confirm
彈窗 ——彈出一個確認框,提供“確定”和“取消”兩個按鈕,并返回布爾值:
- 點擊“確定”返回
true
。 - 點擊“取消”返回
false
。