使用JavaScript实现一个代办事项的小案例

核心功能:

  • 添加任务(add按钮)
  • 完成任务(mark按钮,完成后任务不可点击修改按钮)
  • 修改任务(update按钮,修改任务期间不可点击完成和删除按钮)
  • 删除任务(delete按钮)

HTNL部分代码

html 复制代码
<body>
  <div class="container">
    <!-- 输入框 -->
    <form action="" class="form">
      <input type="text" class="text">
      <input type="button" value="add" class="btn">
    </form>

    <!-- 内容区 -->
    <table border="1" class="content">
      <thead>
        <tr>
          <th class="item-oper">代办事项</th>
          <th id="operate" class="item-oper">操作</th>
        </tr>
      </thead>
      <tbody>
      	<!-- 使用JavaScript生成任务列表 -->
      </tbody>
    </table>
  </div>
</body>
  • 输入框:是进行添加任务
  • 内容区:是添加完任务后,通过JavaScript生成任务列表,对列表进行其它的操作

CSS样式代码

css 复制代码
*{
  margin: 0;
  padding: 0;
  font-family: '怒放字体';
  border-radius: 2px;
}
@font-face {
  font-family: '怒放字体';
  src: url(../font/GongFanNuFangTi\(TaoBaoSouGongFanZiKuKeMaiDanZiShouQuan\)-2.ttf);
}

.container{
  width: 400px;
  margin: 200px auto 0;
}

/* 输入框 */
.form{
  display: flex;
}
.text{
  width: 360px;
  outline: none;     /* 外轮廓去掉 */
  border: solid 1px;
  padding: 3px;
}
.btn{
  width: 40px;
  height: 26px;
  border: solid 1px;
  background: #ace3f4;
}

/* 内容区 */
.content{
  margin-top: 15px;
  width: 100%;
}
.item-oper{
  text-align: center;
  border: black solid 1px;
  border-radius: 2px;
  background: #ace3f4;
}
#operate{
  width: 150px;
}
td{
  font-size: 14px;
  /* text-decoration: line-through; */
}
tr td:nth-child(2){
  text-align: center;
  padding: 2px 3px;
}
tr td:nth-child(2) input{
  border-width: 1px;
  margin: 0 2px;
}

通过HTML和CSS,简易的代办事项雏形已完成:

现在通过JavaScript来进行事件绑定,实现任务的添加修改删除完成

JavaScript代码

添加事件

  • 添加事件要创建表格:第一个单元格放置添加内容,第二个单元格放置内容操作按钮,将单元格放置在tbody标签内
  • 输入框中的字符串前后空格去掉,且不能添加空内容
    • trim():作用是去掉字符全前后的空格
  • 任务添加后,输入框中的内容清空
javascript 复制代码
// 添加事件
var btn = document.querySelector(".btn")
var text = document.querySelector(".text")
var tbody = document.querySelector("tbody")

btn.onclick = function(){ //绑事件,事件触发之后,才执行
  if(text.value.trim()!=""){//如果输入不为空执行下面操作
    // 添加表格标签
    var tr = document.createElement("tr")//创建tr标签
    var td1 = document.createElement("td")//创建td标签
    var td2 = document.createElement("td")//创建td标签

    td1.innerHTML = text.value.trim()//第一个单元格赋输入的内容  trim()作用是去掉空格
    td2.innerHTML = '<input type="button" value="mark" class="mark">'+
          '<input type="button" value="delete" class="delete">'+
          '<input type="button" value="update" class="update"></input>'//第二个单元格赋按钮

    tr.appendChild(td1)
    tr.appendChild(td2)//将两个td标签放置在tr标签内
    tbody.appendChild(tr)//将tr放置在tbody标签内

    text.value = ""//添加后,输入框内容清空
  }
}

删除事件

  • 由于删除按钮是任务添加后才有的操作,所以要写在btn.onclick = function()操作中
  • 找到要删除的内容,询问是否确定要删除,防止误点删除按钮的问题
    • confirm(""):作用询问框
javascript 复制代码
btn.onclick = function(){
  // 删除事件
  var deletes = document.querySelectorAll(".delete")
  for(var i=0;i<deletes.length;i++){
    deletes[i].onclick = function(){//绑事件
      var target = this.parentElement.parentElement//找要删除的标签
      
      if(confirm("确定要删除吗?")){
        tbody.removeChild(target)
      }
    }
  }
}

完成事件

  • 由于完成按钮是任务添加后才有的操作,所以要写在btn.onclick = function()操作中
javascript 复制代码
var endCompleted//完成的事项

btn.onclick = function(){
  // 完成事件
  var marks = document.querySelectorAll(".mark")
  for(var i=0;i<marks.length;i++){
    marks[i].onclick = function(){//绑事件
      var target = this.parentElement.previousElementSibling
      target.style.textDecoration = "line-through"
      target.style.color = "#a4b0be"
      target.style.background = "#f1f2f6"

      endCompleted = this.parentElement.parentElement//完成的事项
      tbody.appendChild(endCompleted)
    }
  }
}

优化1:只用完成的待办事项才能删除

优化删除事件中的代码,设置只有完成的才能删除:

javascript 复制代码
if(this.parentElement.previousElementSibling.style.textDecoration == "line-through"){//设置只有完成的才能删除
   if(confirm("确定要删除吗?")){
     tbody.removeChild(target)
   }
 } else {
   alert("完成才能删除!!!请努力完成吧!!!")
 }

优化2:完成的待办事项在最底部,新添加的任务在完成的上面

优化添加事件中的代码,设置新任务插入到完成事项的上面:

javascript 复制代码
var fistCompleted = tbody.querySelector('tr td[style*="line-through"]')// 插入到tbody的开头(所有已完成事项的上方)
if(fistCompleted){
  tbody.insertBefore(tr, fistCompleted.parentNode)
}else{
  tbody.appendChild(tr)//将tr放置在tbody标签内
}

优化3:完成的事项不需要进行修改

优化完成事件中的代码,添加一个逻辑判断:

javascript 复制代码
if(target.style.textDecoration=='line-through'){
  var updateBtn = this.parentElement.querySelector(".update")
  updateBtn.disabled = true
}

修改事件

  • 由于修改按钮是任务添加后才有的操作,所以要写在btn.onclick = function()操作中
  • 修改事项内容返回到输入框中,且添加按钮改为修改按钮,修改内容后,点击修改按钮,之后输入框内容清空,按钮变会添加按钮
javascript 复制代码
var target_up//全局变量
var markBtn
var deleteBtn
var updates

btn.onclick = function(){
  // 修改事件
  // 第一步:回显
  updates = document.querySelectorAll(".update")
  for(var i=0;i<updates.length;i++){
    updates[i].onclick = function(){//绑事件
      target_up = this.parentElement.previousElementSibling
      text.value = target_up.innerHTML
      btn.value = 'update'
      target_up.style.background = "#f1f2f6"
    }   
  }
  // 第二步:修改
  if(btn.value == 'update'){//判断是添加还是修改按钮
    target_up.innerHTML = text.value
    text.value = ""
    btn.value = "add"
    target_up.style.background = "#fff"
    return
  }
}

优化:修改时,其他的操作按钮不能点击

javascript 复制代码
markBtn = this.parentElement.querySelector(".mark");
deleteBtn = this.parentElement.querySelector(".delete");
markBtn.disabled = true;
deleteBtn.disabled = true;//上面四行代码作用是:修改时,这两个按钮不能点击

JavaScript完整代码

javascript 复制代码
window.onload = function() {

  // 添加事件
  var btn = document.querySelector(".btn")
  var text = document.querySelector(".text")
  var tbody = document.querySelector("tbody")
  var endCompleted//完成的事项
  var target_up//全局变量
  var markBtn
  var deleteBtn
  var updates

  btn.onclick = function(){ //绑事件,事件触发之后,才执行

    // 第二步:修改
    if(btn.value == 'update'){//判断是添加还是修改按钮
      target_up.innerHTML = text.value
      text.value = ""
      btn.value = "add"
      target_up.style.background = "#fff"
      markBtn.disabled = false;
      deleteBtn.disabled = false;//回复按钮
      return
    }

    if(text.value.trim()!=""){//如果输入不为空执行下面操作
      // 添加表格标签
      var tr = document.createElement("tr")//创建tr标签
      var td1 = document.createElement("td")//创建td标签
      var td2 = document.createElement("td")//创建td标签

      td1.innerHTML = text.value.trim()//第一个单元格赋输入的内容  trim()作用是去掉空格
      td2.innerHTML = '<input type="button" value="mark" class="mark">'+
            '<input type="button" value="delete" class="delete">'+
            '<input type="button" value="update" class="update"></input>'//第二个单元格赋按钮

      tr.appendChild(td1)
      tr.appendChild(td2)//将两个td标签放置在tr标签内

      var fistCompleted = tbody.querySelector('tr td[style*="line-through"]')// 插入到tbody的开头(所有已完成事项的上方)
      if(fistCompleted){
        tbody.insertBefore(tr, fistCompleted.parentNode)
      }else{
        tbody.appendChild(tr)//将tr放置在tbody标签内
      }

      text.value = ""//添加后,输入框内容清空
    }


    // 删除事件
    var deletes = document.querySelectorAll(".delete")
    for(var i=0;i<deletes.length;i++){
      deletes[i].onclick = function(){//绑事件
        var target = this.parentElement.parentElement//找要删除的标签
        if(this.parentElement.previousElementSibling.style.textDecoration == "line-through"){//设置只有完成的才能删除
          if(confirm("确定要删除吗?")){
            tbody.removeChild(target)
          }
        } else {
          alert("完成才能删除!!!请努力完成吧!!!")
        }
      }
    }


    // 完成事件
    var marks = document.querySelectorAll(".mark")
    for(var i=0;i<marks.length;i++){
      marks[i].onclick = function(){//绑事件
        var target = this.parentElement.previousElementSibling
        target.style.textDecoration = "line-through"
        target.style.color = "#a4b0be"
        target.style.background = "#f1f2f6"

        endCompleted = this.parentElement.parentElement//完成的事项
        tbody.appendChild(endCompleted)
          
        if(target.style.textDecoration=='line-through'){
          var updateBtn = this.parentElement.querySelector(".update")
          updateBtn.disabled = true
        }
      }
    }


    // 修改事件
    // 第一步:回显
    updates = document.querySelectorAll(".update")
    for(var i=0;i<updates.length;i++){
      updates[i].onclick = function(){//绑事件
        target_up = this.parentElement.previousElementSibling
        text.value = target_up.innerHTML
        btn.value = 'update'
        target_up.style.background = "#f1f2f6"

        markBtn = this.parentElement.querySelector(".mark");
        deleteBtn = this.parentElement.querySelector(".delete");
        markBtn.disabled = true;
        deleteBtn.disabled = true;//上面四行代码作用是:修改时,这两个按钮不能点击
      }   
    }
  }
}