JavaScript-小练习-待办清单

26 阅读9分钟

需求

输入待办内容和选择分类 点击添加按钮添加到未完成区域 未完成区域每个待办都有完成和删除按钮 点击删除 待办消失 点击完成按钮 待办到已完成区域 已完成区域每个待办都有删除按钮 点击删除 待办消失

游戏界面

标签结构 html

输入区域

负责接收用户输入的待办

  • input type=text文本框让用户输入待办内容并且添加placeholder占位符属性 在文本框没有值的时候显示 提示用户输入待办内容
  • select嵌套option标签用来选择待办类型
  • button按钮点击添加待办

输入区域

显示区域

.area嵌套两个类名为finishednotfinisheddiv标签分别表示完成区域和未完成区域 显示区域

代码如下

 <!-- 输入区域 -->
  <div class="input">
    <input type="text" name="" id="" placeholder="输入待办内容">
   <select name="" class="group">
      <option>工作</option>
      <option>生活</option>
      <option>学习</option>
    </select>
    <button class="add">添加</button>
  </div>

  <!-- 显示区域 -->
  <div class="area">
    <div class="finished">
      <p>已完成</p>
    </div>
    <div class="notfinished">
      <p>未完成</p>
    </div>
  </div>

层叠样式 css

  • *通用选择器改变全部的字体为宋体
  • .area display: flex设置为弹性布局:弹性子元素在弹性盒子内一行显示
  • 父元素.area为弹性容器 子元素.finished.notfinished是弹性子元素 然后再分别设置这两个子元素的设置宽高和边框
  • button按钮的样式是在网上找了一个
   * {
      font-family: FangSong;
    }

    .area {
      display: flex;
      justify-content: space-evenly;
      font-size: 15px;
    }

    .finished {
      border: solid 2px pink;
      width: 200px;
      height: 400px;
    }

    .notfinished {
      border: solid 2px skyblue;
      width: 200px;
      height: 400px;
    }

    /* 这个按钮样式是在网上找的 */
    .area button {
      background-color: #EA4C89;
      border-radius: 8px;
      border-style: none;
      box-sizing: border-box;
      color: #FFFFFF;
      cursor: pointer;
      display: inline-block;
      font-family: "Haas Grot Text R Web", "Helvetica Neue", Helvetica, Arial, sans-serif;
      font-size: 10px;
      font-weight: 250;
      height: 20px;
      line-height: 15px;
      list-style: none;
      margin: 0;
      outline: none;
      position: relative;
      text-align: center;
      text-decoration: none;
      transition: color 100ms;
      vertical-align: baseline;
      user-select: none;
      -webkit-user-select: none;
      touch-action: manipulation;
    }

    .area button:hover,
    .area button:focus {
      background-color: #F082AC;
    }

最终布局如下图

最终布局

获取元素 js

document.querySelector返回指定的css选择器中的第一个元素

  • 获取list元素为输入文本框
  • add元素为添加按钮
  • group为待办的种类
  • notdone 分别代表未完成.notfinished和完成.finished区域
 //获取元素
    const list = document.querySelector('input')
    const add = document.querySelector('.add')
    const group = document.querySelector('group')
    const not = document.querySelector('.notfinished')
    const done = document.querySelector('.finished')

数据分析

每一个待办的内容和html标签结构是一一对应的 所以可以存在对象属性的键值对里 通过按钮的点击事件完成对对象键值对的操作再渲染页面

不用数组的原因 对应索引很麻烦 每次操作数据都要把所有数组的索引都一起操作 处理复杂而且代码冗余

  • 未完成区域和完成区域分别用notTextdoneText存储
  • 待办的html标签结构用text字符串来存放
  • 待办具体的内容和分类用value字符串来存放
let notText = {} //未完成
let doneText = {} //完成
let text = '' //list html
let value = '' //list.value+group.value

功能实现

渲染方法

未完成区域

  • 遍历notText对象 将对象属性的值也就是待办的html标签结构累加到not.innerHTML 实现渲染

注意这里用let in 渲染无序对象

  • 未完成区域有完成和删除按钮 所以每次渲染完都要调用finsClick() delsClicknot()方法 后续会把未完成区域的完成和删除按钮的点击事件分别写进这两个方法里
 //渲染未完成区域
    function renderNot() {
      //重新渲染未完成区域
      not.innerHTML = `<p>未完成</p>`
      for (let key in notText) {
        not.innerHTML += notText[key]
      }
      //未完成区域重新渲染之后要重新获取
      finsClick()
      delsClicknot()
    }

完成区域

重新渲染的逻辑和未完成区域相同

  • 完成区域的计划只有删除按钮 渲染完只需要调用 delsClickfin() 后续的完成区域的删除按钮的点击事件就写在这个方法里
//渲染已完成区域
    function renderDone() {
      //重新渲染未完成区域
      done.innerHTML = `<p>已完成</p>`
      for (let key in doneText) {
        done.innerHTML += doneText[key]
      }
      //重新渲染之后要重新获取
      delsClickfin()
    }

添加按钮点击事件

点击添加按钮把计划和删除完成按钮渲染到未完成区域

  • 把列表的html标签(包括完成和删除按钮)放入text变量 把列表内容+分类字符串拼接放进value变量
  • 未完成区域的notText对象的属性键值对中 key键属性名是value字符串 value值是text字符串
  • 更改完之后再 调用 renderNot() 方法 根据notText对象渲染页面
  • 最后再让 list.value清空 下次输入的时候文本框是没有内容的
//添加按钮点击事件
    add.addEventListener('click', function () {
      text = `<p>` + list.value + group.value +
        `<button class="finish" >完成</button>
    <button class="delete"  >删除</button>` + `</p>`
      value = list.value + group.value
      notText[value] = text

      //text渲染
      renderNot()
      list.value = ''
    })

添加按钮效果如下 ![[添加按钮.gif]]

完成按钮点击事件

只有未完成区域有完成按钮

未完成区域的完成按钮

点击按钮把计划和删除按钮渲染到完成区域

  • 获取所有完成按钮
  • 遍历fins类数组 给所有完成按钮添加点击事件来操作notText对象
  • Object.keys(notText)[m]表示notText对象中第m个属性的属性名 里面存放了点击的按钮相对应的待办的具体内容和分类 把这个字符串放进key变量方便使用

Object.keys(obj)方法返回obj数组的属性名key 组成的数组

  • 点击完成按钮之后会把计划内容放进完成区域 完成区域是没有完成按钮的 所以这里text要把完成按钮的标签去掉 再把点击的按钮相对应的待办的具体内容和分类 也就是这里的 key变量放进去
  • 然后操作对象 完成区域 doneTextkey(这里是待办具体内容和分类)属性存放修改过的text 再把未完成区域相应的计划也就是用deletenotTextkey键值对删掉
  • 最后渲染页面 调用 renderNotrenderDone页面 根据对对象的操作 使未完成界面删除这个待办 完成区域渲染上这个待办

注意 未完成区域的完成按钮点击之后 两个区域的对象都会发生变化所以最后要调用renderNot()renderDone()两个方法分别渲染页面

 //未完成区域的完成按钮
    function finsClick() {
      //获取所有fins 按钮
      let fins = document.querySelectorAll('.finish')
      for (let m = 0; m < fins.length; m++) {
        fins[m].addEventListener('click', function () {
          let key = Object.keys(notText)[m]
          //相应的value给text
          text = `<p>` + Object.keys(notText)[m] +
            `<button class="delete">删除</button>` + `</p>`
          //已完成添加
          doneText[key] = text

          //未完成删除
          delete notText[key]

          //根据处理完的元素渲染页面
          renderNot()
          renderDone()

        })
      }
    }

效果如下 完成按钮

删除按钮点击事件

点击删除 把计划删除 两个区域的删除按钮分开写是方便找到按钮相应的对象的key值 完成区域和未完成区域的删除按钮 删除作用到的对象是不一样的 要分开获取

注意 未完成区域和完成区域的删除按钮点击之后 只有这个区域的对象会发生变化所以最后只需要调用一个相应区域的渲染方法来渲染页面就行

未完成区域的删除按钮

  • 获取.notfinished区域所有的删除按钮 这里css选择器选中的是.notfinisheddiv中所有的 .delete按钮
  • 遍历dels类数组 给所有未完成区域删除按钮添加点击事件来操作notText对象
  • 变量key存放 未完成区域的相应的属性名 也就是计划内容
  • delete删除notText对象被点击的相应键值对
  • 最后根据notText对象变化 调用 renderNot方法渲染未完成区域
//未完成区域删除按钮
    function delsClicknot() {
      let dels1 = document.querySelectorAll('.notfinished .delete')
      for (let m = 0; m < dels1.length; m++) {
        dels1[m].addEventListener('click', function () {
          key = Object.keys(notText)[m]
          delete notText[key]
          renderNot()
        })
      }
    }

效果如下 未完成区域删除

完成区域的删除按钮

这里和未完成区域的删除按钮的思路是一样的

  • 获取.finished区域所有的删除按钮
  • 遍历dels类数组 给所有完成区域删除按钮添加点击事件来操作doneText对象
  • 变量key存放 完成区域的被点击的相应的属性名 这里就是相应的计划内容
  • delete删除doneText对象相应键值对
  • 最后根据doneText对象变化 调用 renderDone方法渲染未完成区域渲染完成区域
 //完成区域删除按钮
    function delsClickfin() {
      let dels2 = document.querySelectorAll('.finished .delete')
      for (let n = 0; n < dels2.length; n++) {
        dels2[n].addEventListener('click', function () {
          key = Object.keys(doneText)[n]
          delete doneText[key]
          renderDone()
        })
      }
    }

效果如下 完成区域删除

最终代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>尝试用对象id处理数据</title>
</head>

<body>
  <!-- 输入区域 -->
  <div class="input">
    <input type="text" name="" id="" placeholder="输入待办内容">
    <select name="" id="group">
      <option>工作</option>
      <option>生活</option>
      <option>学习</option>
    </select>
    <button class="add">添加</button>
  </div>

  <!-- 显示区域 -->
  <div class="area">
    <div class="finished">
      <p>已完成</p>
    </div>
    <div class="notfinished">
      <p>未完成</p>
    </div>
  </div>


  <style>
    * {
      font-family: FangSong;
    }

    .area {
      display: flex;
      justify-content: space-evenly;
      font-size: 15px;
    }

    .finished {
      border: solid 2px pink;
      width: 200px;
      height: 400px;
    }

    .notfinished {
      border: solid 2px skyblue;
      width: 200px;
      height: 400px;
    }

    /* 这个按钮样式是在网上找的 */
    .area button {
      background-color: #EA4C89;
      border-radius: 8px;
      border-style: none;
      box-sizing: border-box;
      color: #FFFFFF;
      cursor: pointer;
      display: inline-block;
      font-family: "Haas Grot Text R Web", "Helvetica Neue", Helvetica, Arial, sans-serif;
      font-size: 10px;
      font-weight: 250;
      height: 20px;
      line-height: 15px;
      list-style: none;
      margin: 0;
      outline: none;
      position: relative;
      text-align: center;
      text-decoration: none;
      transition: color 100ms;
      vertical-align: baseline;
      user-select: none;
      -webkit-user-select: none;
      touch-action: manipulation;
    }

    .area button:hover,
    .area button:focus {
      background-color: #F082AC;
    }
  </style>
  <script>
    //获取元素
    const list = document.querySelector('input')
    const add = document.querySelector('.add')
    const group = document.getElementById('group')
    const not = document.querySelector('.notfinished')
    const done = document.querySelector('.finished')


    let notText = {} //未完成
    let doneText = {} //完成
    let text = '' //list html
    let value = '' //list.value+group.value

    //添加按钮点击事件
    add.addEventListener('click', function () {
      text = `<p>` + list.value + group.value +
        `<button class="finish" >完成</button>
    <button class="delete"  >删除</button>` + `</p>`
      value = list.value + group.value
      notText[value] = text

      //text渲染
      renderNot()
      list.value = ''
    })

    //完成和删除按钮点击事件 
    //未完成区域的完成按钮
    function finsClick() {
      //获取所有fins 按钮
      let fins = document.querySelectorAll('.finish')
      for (let m = 0; m < fins.length; m++) {
        fins[m].addEventListener('click', function () {
          let key = Object.keys(notText)[m]
          //相应的value给text
          text = `<p>` + key +
            `<button class="delete">删除</button>` + `</p>`
          //已完成添加
          doneText[key] = text

          //未完成删除
          delete notText[key]

          //根据处理完的元素渲染页面
          renderNot()
          renderDone()

        })
      }
    }


    //未完成区域删除按钮
    function delsClicknot() {
      let dels1 = document.querySelectorAll('.notfinished .delete')
      for (let m = 0; m < dels1.length; m++) {
        dels1[m].addEventListener('click', function () {
          key = Object.keys(notText)[m]
          delete notText[key]
          renderNot()
        })
      }
    }


    //完成区域删除按钮
    function delsClickfin() {
      let dels2 = document.querySelectorAll('.finished .delete')
      for (let n = 0; n < dels2.length; n++) {
        dels2[n].addEventListener('click', function () {
          key = Object.keys(doneText)[n]
          delete doneText[key]
          renderDone()
        })
      }
    }


    //渲染未完成区域
    function renderNot() {
      //重新渲染未完成区域
      not.innerHTML = `<p>未完成</p>`
      for (let key in notText) {
        not.innerHTML += notText[key]
      }
      //未完成区域重新渲染之后要重新获取
      finsClick()
      delsClicknot()
    }

    //渲染已完成区域
    function renderDone() {
      //重新渲染未完成区域
      done.innerHTML = `<p>已完成</p>`
      for (let key in doneText) {
        done.innerHTML += doneText[key]
      }
      //重新渲染之后要重新获取
      delsClickfin()
    }


  </script>
</body>

</html>