前端【8】HTML+CSS+javascript實戰項目----實現一個簡單的待辦事項列表 (To-Do List)

目錄

一、功能需求

二、 HTML

三、CSS

四、js

1、綁定事件與初始設置

2.、綁定事項?

(1)添加操作:

(2)完成操作

(3)刪除操作

(4)修改操作

3、完整js代碼

總結與感悟


????????實現了一個包括 添加、完成、刪除、修改 等操作的 To-Do List,涵蓋了常見的 DOM 操作及事件綁定。目的為了掌握 JavaScript 操作 DOM 的技巧,項目還可用于實際開發中的簡單任務管理工具。

一、功能需求

  1. 添加待辦事項

    • 用戶輸入內容后,點擊 "添加" 按鈕,將事項添加到列表中。
    • 如果輸入為空,提示用戶輸入內容。
  2. 標記完成

    • 點擊 "完成" 按鈕,可以標記當前事項為完成或取消完成。
  3. 刪除事項

    • 僅當事項已標記完成時才能刪除。
  4. 修改事項

    • 點擊 "修改" 按鈕,將事項內容回填到輸入框,用戶可以修改內容并保存。

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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67327.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67327.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67327.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++標準線程庫實現優雅退出的方式

目錄 1.通過設置共享退出標記 2.使用std::jthread創建線程 3.定義消息類型的方式 4.注意事項 1.通過設置共享退出標記 定義一個退出變量bool stop false; 表示線程是否應該停止。在主線程中設置標記stoptrue,然后join一直等待&#xff0c;然后線程循環檢測到stop是否為tru…

Java學習教程,從入門到精通,JDBC插入記錄語法及案例(104)

JDBC插入記錄語法及案例 一、JDBC插入記錄語法 在JDBC中&#xff0c;插入記錄主要通過執行SQL的INSERT語句來實現。其基本語法如下&#xff1a; INSERT INTO 表名 (列1, 列2, ..., 列n) VALUES (值1, 值2, ..., 值n);表名&#xff1a;需要插入記錄的表的名稱。列1, 列2, …,…

vue事件總線(原理、優缺點)

目錄 一、原理二、使用方法三、優缺點優點缺點 四、使用注意事項具體代碼參考&#xff1a; 一、原理 在Vue中&#xff0c;事件總線&#xff08;Event Bus&#xff09;是一種可實現任意組件間通信的通信方式。 要實現這個功能必須滿足兩點要求&#xff1a; &#xff08;1&#…

圖像處理之HSV顏色空間

目錄 1 RGB 的局限性 2 HSV 顏色空間 3 RGB與HSV相互轉換 4 HSV顏色模型對圖像的色相、飽和度和明度進行調節 5 演示Demo 5.1 開發環境 5.2 功能介紹 5.3 下載地址 參考 1 RGB 的局限性 RGB 是我們接觸最多的顏色空間&#xff0c;由三個通道表示一幅圖像&#xff0c;分…

DeepSeek是由杭州深度求索人工智能基礎技術研究有限公司(簡稱“深度求索”)發布的一系列人工智能模型

DeepSeek是由杭州深度求索人工智能基礎技術研究有限公司&#xff08;簡稱“深度求索”&#xff09;發布的一系列人工智能模型&#xff0c;其在知識類任務上展現出了卓越的性能。以下是對DeepSeek的詳細介紹&#xff0c;內容雖無法達到10000字&#xff0c;但會盡可能全面且深入地…

【C++高并發服務器WebServer】-9:多線程開發

本文目錄 一、線程概述1.1 線程和進程的區別1.2 線程之間共享和非共享資源1.3 NPTL 二、線程操作2.1 pthread_create2.2 pthread_exit2.3 pthread_join2.4 pthread_detach2.5 patch_cancel2.6 pthread_attr 三、實戰demo四、線程同步五、死鎖六、讀寫鎖七、生產消費者模型 一、…

14-6-1C++STL的list

(一&#xff09;list容器的基本概念 list容器簡介&#xff1a; 1.list是一個雙向鏈表容器&#xff0c;可高效地進行插入刪除元素 2.list不可以隨機存取元素&#xff0c;所以不支持at.(pos)函數與[ ]操作符 &#xff08;二&#xff09;list容器頭部和尾部的操作 list對象的默…

在sortablejs的拖拽排序情況下阻止input拖拽事件

如題 問題 在vue3的elementPlus的table中&#xff0c;通過sortablejs添加了行拖拽功能&#xff0c;但是在行內會有輸入框&#xff0c;此時拖拽輸入框會觸發sortablejs的拖拽功能 解決 基于這個現象&#xff0c;我懷疑是由于拖拽事件未綁定而冒泡到后面的行上從而導致的拖拽…

21.Word:小趙-畢業論文排版?【39】

目錄 題目? NO1.2 NO3.4 NO5.6 NO7.8.9 NO10.11.12 題目 NO1.2 自己的論文當中接收老師的修改&#xff1a;審閱→比較→源文檔&#xff1a;考生文件夾&#xff1a;Word.docx→修訂的文檔&#xff1a;考生文件夾&#xff1a;教師修改→確定→接收→接收所有修訂將合并之…

leetcode_鏈表 876.鏈表的中間節點

876.鏈表的中間節點 給你單鏈表的頭結點 head &#xff0c;請你找出并返回鏈表的中間結點。如果有兩個中間結點&#xff0c;則返回第二個中間結點。思路&#xff1a;快慢指針&#xff0c;創建兩個指針fast和slow&#xff0c;fast指針每次移動兩步&#xff0c;slow指針每次移動…

深度學習 DAY3:NLP發展史及早期的前饋神經網絡(ANN)及多任務學習

NLP發展史 NLP發展脈絡簡要梳理如下&#xff1a; 2001 - Neural language models&#xff08;神經語言模型&#xff09; 2008 - Multi-task learning&#xff08;多任務學習&#xff09; 2013 - Word embeddings&#xff08;詞嵌入&#xff09; 2013 - Neural networks for NL…

全面了解 Web3 AIGC 和 AI Agent 的創新先鋒 MelodAI

不管是在傳統領域還是 Crypto&#xff0c;AI 都是公認的最有前景的賽道。隨著數字內容需求的爆炸式增長和技術的快速迭代&#xff0c;Web3 AIGC&#xff08;AI生成內容&#xff09;和 AI Agent&#xff08;人工智能代理&#xff09;正成為兩大關鍵賽道。 AIGC 通過 AI 技術生成…

54.數字翻譯成字符串的可能性|Marscode AI刷題

1.題目 問題描述 小M獲得了一個任務&#xff0c;需要將數字翻譯成字符串。翻譯規則是&#xff1a;0對應"a"&#xff0c;1對應"b"&#xff0c;依此類推直到25對應"z"。一個數字可能有多種翻譯方法。小M需要一個程序來計算一個數字有多少種不同的…

FileReader使用

FileReader : 讀取文件內容的api&#xff0c;&#xff0c;&#xff0c;在前端處理上傳的文件&#xff0c;&#xff0c;比如預覽圖片 readAsDataURL(file) &#xff1a; 讀取為base64編碼的 data urlreadAsText() &#xff1a; 讀取為文本readAsArrayBuffer() : 讀取為二進制 …

RabbitMQ5-死信隊列

目錄 死信的概念 死信的來源 死信實戰 死信之TTl 死信之最大長度 死信之消息被拒 死信的概念 死信&#xff0c;顧名思義就是無法被消費的消息&#xff0c;一般來說&#xff0c;producer 將消息投遞到 broker 或直接到queue 里了&#xff0c;consumer 從 queue 取出消息進…

JavaScript系列(48)-- 3D渲染引擎實現詳解

JavaScript 3D渲染引擎實現詳解 &#x1f3ae; 今天&#xff0c;讓我們深入探討JavaScript的3D渲染引擎實現。通過WebGL和現代JavaScript技術&#xff0c;我們可以構建一個功能完整的3D渲染系統。 3D渲染基礎概念 &#x1f31f; &#x1f4a1; 小知識&#xff1a;3D渲染引擎的…

10JavaWeb——SpringBootWeb案例01

前面我們已經講解了Web前端開發的基礎知識&#xff0c;也講解了Web后端開發的基礎(HTTP協議、請求響應)&#xff0c;并且也講解了數據庫MySQL&#xff0c;以及通過Mybatis框架如何來完成數據庫的基本操作。 那接下來&#xff0c;我們就通過一個案例&#xff0c;來將前端開發、后…

【面試題】 Java 三年工作經驗(2025)

問題列表 為什么選擇 spring boot 框架&#xff0c;它與 Spring 有什么區別&#xff1f;spring mvc 的執行流程是什么&#xff1f;如何實現 spring 的 IOC 過程&#xff0c;會用到什么技術&#xff1f;spring boot 的自動化配置的原理是什么&#xff1f;如何理解 spring boot 中…

JAVA 接口、抽象類的關系和用處 詳細解析

接口 - Java教程 - 廖雪峰的官方網站 一個 抽象類 如果實現了一個接口&#xff0c;可以只選擇實現接口中的 部分方法&#xff08;所有的方法都要有&#xff0c;可以一部分已經寫具體&#xff0c;另一部分繼續保留抽象&#xff09;&#xff0c;原因在于&#xff1a; 抽象類本身…

ResNeSt: Split-Attention Networks論文學習筆記

這張圖展示了一個名為“Split-Attention”的神經網絡結構&#xff0c;該結構在一個基數組&#xff08;cardinal group&#xff09;內進行操作。基數組通常指的是在神經網絡中處理的一組特征或通道。圖中展示了如何通過一系列操作來實現對輸入特征的注意力機制。 以下是圖中各部…