todoList清单(HTML+CSS+JavaScript)

news2024/11/17 6:46:39

   🌏个人博客主页:

前言: 前段时间学习了JavaScript,然后写了一个todoList小项目,现在和大家分享一下我的清单以及如何实现的,希望对大家有所帮助

🔥🔥🔥文章专题todoList清单

😽感谢大家的点赞👍收藏⭐️评论✍您的一键三连是我更新的动力 💓 


 清单效果:

页面展示: 

 tab-工作-tab-生活-tab-学习-tab-健康:

功能介绍和代码详细解释:

我一共写了4个页面,但是每个页面都是基本一样的,所以我通过第一个页面向大家展示我的功能都有哪些并且是如何实现的

大体思路: 

现在我来介绍一下我大体是如何实现的,首先我创造两个二维数组(一个arrList1数组储存我的未完成内容,一个arrList2数组储存我的已完成内容),还有一个全局变量   dataId,dataId在这里的作用非常大,dataId通过tab点击可以改变我的dataId的内容,然后显示我的第几个页面和改变我的二维数组的第一个下标的值(四个页面我都设置了相class=“note”属性,所以可以通过tab关联的dataId显示我的第几个note和转换我的第几个数组

提示:(第一个页面是我的arrList1[0]和arrList2[0])

每一个页面的内容的存储都相当于两个一维数组

 1 全局dataId和二维数组显示:
  // 判断到第几个note
  let dataId = 1
  //定义数组
  if (!this.localStorage.getItem('arr')) {
    localStorage.setItem('arr', "[[], [], [], []]")

  } else if (!this.localStorage.getItem('arr1')) {
    localStorage.setItem('arr1', "[[], [], [], []]")
  }
  //我的未完成数组
  const arrList1 = JSON.parse(localStorage.getItem('arr'))
  //我的已完成数组
  const arrList2 = JSON.parse(localStorage.getItem('arr1'))
2 更新未完成和已完成:

因为更新已完成和未完成相似 ,所以下面我就通过更新未完成来和大家讲解,关于更新添加,我是通过将我的本地存储解析成数组然后遍历将这些内容通过join返回成一个字符串,添加到我的un_ul里面,最终显示在页面当中

// 更新未完成
  function renderUnfinished() {
    let un_ul = document.querySelector(`.note:nth-child(${dataId}) .uul-unfinished`);
    const listItems = JSON.parse(localStorage.getItem('arr'))[dataId - 1].map((taskText, index) => {
      return `
      <li>
        <a href="#" class="task-icon finished" data-name="${index}"></a>
        <div class="center-item">${taskText}</div>
        <div class="timing">
          定时
          <select data-name="${index}" id="timing-list" class="timeNum">
            <option value="0">0min</option>
            <option value="1">1min</option>
            <option value="2">2min</option>
            <option value="3">3min</option>
            <option value="4">4min</option>
            <option value="5">5min</option>
          </select>
        </div>
        <div class="delete task-icon" data-id="${index}"></div>
      </li>
    `
    }).join('')
    console.log(JSON.parse(localStorage.getItem('arr'))[dataId - 1])
    un_ul.innerHTML = listItems
  }

  // 更新已完成
  function renderFinished() {
    let ul = document.querySelector(`.note:nth-child(${dataId}) .uul-finished`)

    const listItems = JSON.parse(localStorage.getItem('arr1'))[dataId - 1].map((taskText, index) => {
      return `
      <li>
        <a href="#" class="task-icon finished"  data-name="${index}"></a>
        <div class="center-item">${taskText}</div>
        <div class="timing">
          定时
          <select data-name="${index}" id="timing-list" class="timeNum">
            <option value="0">0min</option>
          </select>
        </div>
        <div class="delete task-icon" data-id="${index}"></div>
      </li>
    `
    }).join('')

    ul.innerHTML = listItems
  }
3 input输入框回车输入内容:

 第一步获得我的input标签,然后我给我的input标签添加键盘事件监听,如果监听到点击键盘的回车Enter键,并且我的内容不为空,然后就添加给我的数组和我的本地存储,并且通过我的 renderUnfinished方法进行显示,最后将我的input标签内容变为空

  // 如果按下了回车事件
  let inputTask = document.querySelector('#task')
  inputTask.addEventListener('keydown', function (e) {
    if (e.key === 'Enter') {
      let newTaskText = inputTask.value.trim()
      if (newTaskText !== '') {
        arrList1[dataId - 1].push(newTaskText)
        localStorage.setItem('arr', JSON.stringify(arrList1))
        //更新未完成事件界面
        renderUnfinished()
        //将input设为空
        inputTask.value = ''
      }
    }
  })
4 点击删除未完成:

 首先给父级元素添加点击事件,通过dataID来获得是第几个li标签然后删除该位置的数组内容(dataID和一维数组是关联的)通过dataID可以当中数组下标得到内容所以可以直接使用dataID进行数组操作,定位到第几个内容然后直接进行删除操作,然后改变本地存储,最后进行遍历显示

    // 删除未完成
    //un_ul是存储内容li的父级ul标签,这里使用冒泡来获得li
    un_ul.addEventListener('click', function (e) {
      //判断点击的是否是delete小图标
      if (e.target.classList.contains('delete')) {
        let dataID = parseInt(e.target.dataset.id)
        arrList1[dataId - 1].splice(dataID, 1)
        console.log(arrList1)
        //往本地存储添加相同密匙的内容只会覆盖
        localStorage.setItem('arr', JSON.stringify(arrList1))
        renderUnfinished()

      }
    })
5 点击删除已完成:

这里的操作和上面的删除未完成操作一样,只是获取的父级元素不一样

    // 删除已完成
    ul.addEventListener('click', function (e) {
      if (e.target.classList.contains('delete')) {
        let dataID = parseInt(e.target.dataset.id)
        // console.log(dataID)
        arrList2[dataId - 1].splice(dataID, 1)

        localStorage.setItem('arr1', JSON.stringify(arrList2))
        renderFinished()
      }
    })
6 删除全部未完成:

这个就是点击全部已完成的按钮,然后将数组和本地存储清空,最后进行更新

    //删除全部已完成
    text1.addEventListener('click', function (e) {
      if (e.target.tagName === 'SPAN') {
        arrList2[dataId - 1] = []
        localStorage.setItem('arr1', JSON.stringify(arrList2))
        renderFinished()
      }
    })
7 点击圆形图标未完成变成已完成:

这个就是点击li标签的第一个小图标,然后使得该内容从未完成变成已完成,内部操作就是点击该图标,通过dataName为下标来获得该处的内容,然后将该内容添加到已完成的数组里面,最后将该内容在未完成里面删除,最后修改本地存储,然后进行更新

    // 点击未完成按钮任务变成完成
    un_ul.addEventListener('click', function (e) {
      if (e.target.classList.contains('finished')) {
        let dataName = parseInt(e.target.dataset.name);
        arrList2[dataId - 1].push(arrList1[dataId - 1][dataName]);
        arrList1[dataId - 1].splice(dataName, 1);
        localStorage.setItem('arr1', JSON.stringify(arrList2));
        localStorage.setItem('arr', JSON.stringify(arrList1));
        renderFinished();
        renderUnfinished();
      }
    })

8 时间提醒:

这个是我的select标签里面的option进行的change 才会触发事件监听,虽然还是冒泡,但是在if语句里面进行了判断,开始获得事件,然后添加了计时器将时间每秒减一次,当时间为0时重复上面的未完成功能到已完成的操作

  // 时间提醒
    un_ul.addEventListener('change', function (e) {
      if (e.target && e.target.classList.contains('timeNum')) {
        let timer = +e.target.value;
        let time = setInterval(function () {
          timer--;
          let dataName = parseInt(e.target.dataset.name);
          if (timer === 0) {
            arrList2[dataId - 1].push(arrList1[dataId - 1][dataName]);
            arrList1[dataId - 1].splice(dataName, 1);
            localStorage.setItem('arr', JSON.stringify(arrList1));
            localStorage.setItem('arr1', JSON.stringify(arrList2));
            renderFinished();
            renderUnfinished();
            alert('滴滴,时间到');
            clearInterval(time);
          }
        }, 1000)
      }
    })
9 计时器

获得当前时间进行显示 ,然后通过计时器每秒更改一次时间


  // 显示当前时间
  function showTime() {

    let date = new Date()

    // 年月日
    let year = date.getFullYear()
    let month = date.getMonth() + 1
    let day = date.getDate()

    // 时分秒
    let hour = date.getHours()
    hour = hour < 10 ? '0' + hour : hour
    let minute = date.getMinutes()
    minute = minute < 10 ? '0' + minute : minute
    let second = date.getSeconds()
    second = second < 10 ? '0' + second : second

    // 显示
    let element = document.getElementById('date')
    element.innerHTML = '<p>' + year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second + '</p>'
  }

  let ShowTime = window.setInterval(showTime, 1000)

 全部代码展示:

HTML:
<body>
  <p id="date"></p>
  <!-- 设置便签整体 -->
  <div class="entire">
    <div class="title"><img class="pic" src="./image/title.png"><img class="pic1" src="./image/bianqian.png">
    </div>
    <!-- 设置便签头部 -->
    <div class="header">
      <!-- 添加输入框 -->
      <input id="task" type="text" placeholder="添加请按回车键">

    </div>

    <!-- 设置中部 -->
    <div class="middle">
      <!-- 设置中间tab栏部分 -->
      <div class="tabs">
        <!-- 设置4个内容便签tab -->
        <div class="work active" data-id="1">工作</div>
        <div class="life" data-id="2">生活</div>
        <div class="study" data-id="3">学习</div>
        <div class="health" data-id="4">健康</div>
      </div>

      <!-- 设置中间内容部分 -->
      <div class="content">

        <!-- 设置第一个便签内容 -->
        <div class="note active">
          <div class="work-unfinished">
            <div class="note-text">未完成</div>
            <!-- 定时 -->
            <ul class="uul-unfinished">
              <!-- 通过dom添加li标签 -->
              <!-- <li>
                <a href="#" class="task-icon finished" data-name="1"></a>
                <div class="center-item">吃饭</div>
                <div class="timing">
                  定时
                  <select data-name="${index}" id="timing-list" class="timeNum">
                    <option value="0">0min</option>
                    <option value="1">1min</option>
                    <option value="2">2min</option>
                    <option value="3">3min</option>
                    <option value="4">4min</option>
                    <option value="5">5min</option>
                  </select>
                </div>
                <div class="delete task-icon" data-id="1"></div>
              </li> -->
            </ul>
          </div>
          <div class="work-finished">
            <div class="text">
              <div class="note-text">已完成</div>
              <span class="deleteAll">删除全部</span>
              <img src="./image/unfinished.png">
            </div>
            <!-- 定时 -->
            <ul class="uul-finished">
              <!-- 通过dom添加li标签 -->
              <!-- <li>
                <a href="#" class="task-icon unfinished"></a>
                <div class="center-item">${taskText}</div>
                <div class="timing">
                  定时
                  <select data-name="1" id="timing-list" class="timeNum">
                    <option value="0">0min</option>
                  </select>
                </div>
                <div class="delete task-icon" data-id="${index}"></div>
              </li> -->
            </ul>
          </div>
        </div>

        <!-- 设置第二个便签内容 -->
        <div class="note">
          <div class="life-unfinished">
            <div class="note-text">未完成</div>
            <!-- 定时 -->
            <ul class="uul-unfinished">
              <!-- 通过dom添加li标签 -->
            </ul>
          </div>
          <div class="life-finished">
            <div class="text">
              <div class="note-text">已完成</div>
              <span class="deleteAll">删除全部</span>
              <img src="./image/unfinished.png">
            </div>
            <!-- 定时 -->
            <ul class="uul-finished">
              <!-- 通过dom添加li标签 -->
            </ul>
          </div>
        </div>

        <!-- 设置第三个便签内容 -->
        <div class="note">
          <div class="study-unfinished">
            <div class="note-text">未完成</div>
            <!-- 定时 -->
            <ul class="uul-unfinished">
              <!-- 通过dom添加li标签 -->
            </ul>
          </div>
          <div class="study-finished">
            <div class="text">
              <div class="note-text">已完成</div>
              <span class="deleteAll">删除全部</span>
              <img src="./image/unfinished.png">
            </div>
            <!-- 定时 -->
            <ul class="uul-finished">
              <!-- 通过dom添加li标签 -->
            </ul>
          </div>
        </div>

        <!-- 设置第四个便签内容 -->
        <div class="note">
          <div class="health-unfinished">
            <div class="note-text">未完成</div>
            <!-- 定时 -->
            <ul class="uul-unfinished">
              <!-- 通过dom添加li标签 -->
            </ul>
          </div>
          <div class="health-finished">
            <div class="text">
              <div class="note-text">已完成</div>
              <span class="deleteAll">删除全部</span>
              <img src="./image/unfinished.png">
            </div>
            <!-- 定时 -->
            <ul class="uul-finished">
              <!-- 通过dom添加li标签 -->
            </ul>
          </div>
        </div>

      </div>
    </div>

  </div>

  </div>
  <script src="./todoList.js"></script>
</body>

CSS:
* {
  margin: 0;
  margin: 0;
  box-sizing: border-box;
}

li {
  list-style: none;
}

a {
  text-decoration: none;
}

body {
  background-color: #fffbfb;
  background-image: url(./image/bigbgc.png);
  height: 1300px;
  background-repeat: no-repeat;
  background-size: cover;
  user-select: none;
}

#date {
  text-align: center;
  height: 80px;
  font-size: 50px;
  color: #fff;
}

.entire {
  margin: auto;
  width: 600px;
  height: 1100px;
  border-radius: 45px;
  border: 1px solid rgb(228, 228, 255);
  box-shadow: 5px 5px 15px rgb(201, 198, 198), -5px -5px 10px #fff;
  background-color: #ffefef;
  /* background-image: url(./image/bgc.png);
  background-size: contain; */
}

.task-icon {
  cursor: pointer;
  font-family: 'icomoon';
  display: inline-block;
  width: 40px;
  height: 40px;
  font-size: 40px;
  text-align: center;
  border-radius: 20px;
  /* box-shadow: 5px 5px 5px rgb(255, 255, 255), 5px 5px 5px #fffdfd; */
  color: #ffffff;
  margin-right: 10px;
  margin-bottom: 9px;
}

.life-finished .task-icon,
.life-unfinished .task-icon {
  color: #ffd1d1;
}

.health-finished .task-icon,
.health-unfinished .task-icon {
  color: #dde6ff;
}

.title {
  margin: auto;
  width: 400px;
  height: 100px;
  border-radius: 40px;
  text-align: center;
  box-shadow: 5px 5px 15px rgb(201, 198, 198), -5px -5px 10px #fff;
  margin-bottom: 20px;
}

/* .title span {
  color: #d27171;
  font-size: 30px;
  margin-top: 5px;
  text-align: center;
  vertical-align: middle;
} */

.title .pic {
  width: 80px;
  height: 80px;
  vertical-align: middle;
  margin-top: 10px;
  margin-right: 10px;
}

.title .pic1 {
  border-radius: 12px;
  width: 160px;
  vertical-align: middle;
  margin-top: 10px;
  margin-right: 10px;
}

.header input {
  margin-left: 105px;
  padding-left: 15px;
  width: 390px;
  height: 55px;
  border-radius: 25px;
  border: none;
  outline: none;
  font-size: 22px;
  color: #e09191;
  background-color: #ffefef;
  box-shadow: 5px 5px 15px rgb(219, 218, 218) inset, -5px -5px 10px #fff inset;
}

input::placeholder {
  color: #f2b1b1;
  font-size: 21px;
}

.tabs {
  margin-top: 35px;
  display: flex;
  gap: 10px;
  border-bottom: 2px solid #f0b2b2;
}

.tabs div {
  padding: 10px 20px;
  background-color: #ffefef;
  border: 2px solid #e7b3b3;
  border-top-left-radius: 36px;
  border-top-right-radius: 36px;
  border-bottom: none;
  cursor: pointer;
  color: #e59898;
  box-shadow: 5px 5px 15px rgb(250, 241, 241) inset, -5px -5px 10px #fff inset;
}

.tabs .active {
  background-color: #ffd5d5;
}

.timing {
  width: 140px;
  text-align: center;
}

#timing-list {
  width: 60px;
  color: rgb(206, 168, 168);
  outline: none;
  border-color: rgb(228, 128, 128);
  border-radius: 10px;
  margin-top: 13px;

}

.content {
  padding-top: 15px;
}

.note {
  padding-top: 20px;
  margin: auto;
  width: 560px;
  height: 790px;
  border: 3px solid #f7dfdf;
  border-radius: 40px;

}

.note:nth-child(1) {
  background-color: #ffdddd;
}

.note:nth-child(2) {
  background-color: #fffefe;
}

.note:nth-child(2) .center-item {
  color: #da5d5d;
}

.note:nth-child(3) {
  background-color: #ffdddd;
}

.note:nth-child(3) .center-item {
  color: #ffffff;
}

.note:nth-child(4) {
  background-color: #f8f9ff;
}

.note:nth-child(4) .center-item {
  color: #7d9fb8;
}


/* 设置背景图片 */
.work-unfinished,
.work-finished {
  background-image: url(./image/bgc.png);
}

.life-finished,
.life-unfinished {
  background-image: url(./image/bgc1.png);
  background-size: cover;
}

.study-unfinished,
.study-finished {
  background-image: url(./image/bgc2.png);
}

.health-unfinished,
.health-finished {
  background-image: url(./image/bgc3.png);
}

/* 设置完成和未完成的框的大小和样式 */
.work-unfinished,
.work-finished,
.life-unfinished,
.life-finished,
.study-unfinished,
.study-finished,
.health-unfinished,
.health-finished {
  padding-top: 10px;
  margin: auto;
  height: 360px;
  width: 510px;
  border-radius: 25px;
  border: #eadddd solid 2px;
  box-shadow: 5px 5px 5px rgb(223, 223, 223) inset, -5px -5px 10px #f2e8e8 inset;
}

/* 设置完成和未完成之间的间隔为20px */
.work-unfinished,
.life-unfinished,
.study-unfinished,
.health-unfinished {
  margin-bottom: 20px;
}

/* 设置完成和未完成的字体样式 */
.note-text {
  margin: auto;
  width: 140px;
  height: 50px;
  border-radius: 22px;
  padding-top: 5px;
  color: #d58585;
  font-size: 26px;
  text-align: center;
}

/* 更换第三个标签主题字体颜色 */
.study-unfinished .note-text,
.study-finished .note-text {
  color: #ffffff;
}

/* 更换第一个标签主题颜色 */
.work-finished .note-text,
.work-unfinished .note-text {
  box-shadow: 5px 5px 5px rgb(248, 157, 157) inset, -5px -5px 10px #f2e8e8 inset;
  background-color: #ffdfdf;

}

.life-finished .note-text,
.life-unfinished .note-text {
  box-shadow: 5px 5px 5px rgb(248, 157, 157) inset, -5px -5px 10px #f2e8e8 inset;
  background-color: #fff8f8;
}

.study-unfinished .note-text,
.study-finished .note-text {
  box-shadow: 5px 5px 5px rgb(207, 161, 161) inset, -5px -5px 10px #f2e8e8 inset;
  background-color: #ffc5c5;
}

.health-finished .note-text,
.health-unfinished .note-text {
  box-shadow: 5px 5px 5px #e3f1ff inset, -5px -5px 10px #dbdbdb inset;
  color: #d6e3ff;
  background-color: #ffffff;
}


.work-finished .note-text,
.life-finished .note-text,
.study-finished .note-text,
.health-finished .note-text {
  margin-left: 185px;
}

.uul-unfinished,
.uul-finished {
  margin-top: 5px;
  display: block;
  width: 510px;
  height: 295px;
  overflow-y: scroll;
  overflow-x: hidden;
}


/* 隐藏滚动条  */
.uul-unfinished::-webkit-scrollbar,
.uul-finished::-webkit-scrollbar {
  width: 0;
}

.uul-unfinished li,
.uul-finished li {
  padding: 11px;
  margin-top: 12px;
  margin-left: -10px;
  border-radius: 30px;
  display: flex;
  height: 60px;
  width: 450px;
  text-align: center;
  font-size: 17px;
  color: #c06666;
}

.work-unfinished .uul-unfinished li,
.work-finished .uul-finished li {
  box-shadow: 5px 5px 15px rgb(255, 255, 255) inset, -5px -5px 10px #f2e8e8 inset;
  background-color: #ffc3c3;
}

.life-unfinished .uul-unfinished li,
.life-finished .uul-finished li {
  box-shadow: 5px 5px 5px rgb(255, 211, 211) inset, -5px -5px 10px #f2e8e8 inset;
  background-color: #ffffff;
}

.study-unfinished .uul-unfinished li,
.study-finished .uul-finished li {
  box-shadow: 5px 5px 15px rgb(255, 255, 255) inset, -5px -5px 10px #f2e8e8 inset;
  background-color: #ffa3a3;
}

.health-unfinished .uul-unfinished li,
.health-finished .uul-finished li {
  box-shadow: 5px 5px 15px rgb(255, 255, 255) inset, -5px -5px 10px #e6f8ff inset;
  background-color: #ffffff;
}


.center-item {
  width: 250px;
  height: 20px;
  overflow: hidden;
  margin-top: 10px;
  text-align: left;

}

.uul-finished .center-item {
  text-decoration: line-through;
}

/* .delete {
  cursor: pointer;
  color: #ffffff;
  height: 36px;
  width: 36px;
} */

/* 设置变签内容不可看 */
.note {
  display: none;
}

/* 设置变迁内容可看 */
.content .active {
  display: block;
}

/* 设置完成文字图片在一排 */
.text {
  display: flex;
}

/* 
.deleteAll {
  cursor: pointer;
  background-image: url(./image/unfinished.png);
  width: 50px;
  height: 50px;
} */

.text img {
  width: 30px;
  height: 30px;
  border-radius: 15px;
  margin-right: 10px;
  margin-left: 10px;
  margin-top: 4px;
}


.text span {
  width: 100px;
  height: 40px;
  /* cursor: pointer;/ */
  text-align: center;
  vertical-align: middle;
  color: #8d2222;
  font-size: 20px;
  padding: 4px;
  border-radius: 15px;
  border: 1px solid rgb(255, 217, 142);
}
JS: 
window.addEventListener('load', function () {
  // 判断到第几个note
  let dataId = 1
  //显示时间1
  showTime()
  //定义数组
  if (!this.localStorage.getItem('arr')) {
    localStorage.setItem('arr', "[[], [], [], []]")

  } else if (!this.localStorage.getItem('arr1')) {
    localStorage.setItem('arr1', "[[], [], [], []]")
  }
  const arrList1 = JSON.parse(localStorage.getItem('arr'))
  const arrList2 = JSON.parse(localStorage.getItem('arr1'))


  // 初始化所有标签页的任务列表
  for (let i = 1; i <= 4; i++) {
    dataId = i
    renderUnfinished()
    renderFinished()
  }
  //将dataId重新赋值为1
  dataId = 1

  // 如果按下了回车事件
  let inputTask = document.querySelector('#task')
  inputTask.addEventListener('keydown', function (e) {
    if (e.key === 'Enter') {
      let newTaskText = inputTask.value.trim()
      if (newTaskText !== '') {
        arrList1[dataId - 1].push(newTaskText)
        localStorage.setItem('arr', JSON.stringify(arrList1))
        //更新未完成事件界面
        renderUnfinished()
        //将input设为空
        inputTask.value = ''
      }
    }
  })

  // 点击tabs
  let tabs = document.querySelector('.tabs')
  tabs.addEventListener('click', function (e) {
    if (e.target.tagName === 'DIV' && e.target.hasAttribute('data-id')) {
      document.querySelector('.tabs .active').classList.remove('active')
      e.target.classList.add('active')
      // 判断到第几个note
      console.log(dataId)
      dataId = +e.target.dataset.id
      console.log(dataId)
      // console.log(dataId)
      document.querySelector('.content .active').classList.remove('active')
      document.querySelector(`.content .note:nth-child(${dataId})`).classList.add('active')
      // 更新两个界面
      // renderFinished()
      // renderUnfinished()
      bindEventListeners()
    }
  });

  // 绑定事件监听器
  function bindEventListeners() {
    let un_ul = document.querySelector(`.note:nth-child(${dataId}) .uul-unfinished`)
    let ul = document.querySelector(`.note:nth-child(${dataId}) .uul-finished`)
    let text1 = document.querySelector(`.note:nth-child(${dataId}) .deleteAll`)

    // 删除未完成
    un_ul.addEventListener('click', function (e) {
      if (e.target.classList.contains('delete')) {
        let dataID = parseInt(e.target.dataset.id)
        arrList1[dataId - 1].splice(dataID, 1)
        console.log(arrList1)
        localStorage.setItem('arr', JSON.stringify(arrList1))
        renderUnfinished()

      }
    })

    // 删除已完成
    ul.addEventListener('click', function (e) {
      if (e.target.classList.contains('delete')) {
        let dataID = parseInt(e.target.dataset.id)
        // console.log(dataID)
        arrList2[dataId - 1].splice(dataID, 1)

        localStorage.setItem('arr1', JSON.stringify(arrList2))
        renderFinished()
      }
    })

    //删除全部已完成
    text1.addEventListener('click', function (e) {
      if (e.target.tagName === 'SPAN') {
        arrList2[dataId - 1] = []
        localStorage.setItem('arr1', JSON.stringify(arrList2))
        renderFinished()
      }
    })

    // 点击未完成按钮任务变成完成
    un_ul.addEventListener('click', function (e) {
      if (e.target.classList.contains('finished')) {
        let dataName = parseInt(e.target.dataset.name);
        arrList2[dataId - 1].push(arrList1[dataId - 1][dataName]);
        arrList1[dataId - 1].splice(dataName, 1);
        localStorage.setItem('arr1', JSON.stringify(arrList2));
        localStorage.setItem('arr', JSON.stringify(arrList1));
        renderFinished();
        renderUnfinished();
      }
    })

    // 时间提醒
    un_ul.addEventListener('change', function (e) {
      if (e.target && e.target.classList.contains('timeNum')) {
        let timer = +e.target.value;
        let time = setInterval(function () {
          timer--;
          let dataName = parseInt(e.target.dataset.name);
          if (timer === 0) {
            arrList2[dataId - 1].push(arrList1[dataId - 1][dataName]);
            arrList1[dataId - 1].splice(dataName, 1);
            localStorage.setItem('arr', JSON.stringify(arrList1));
            localStorage.setItem('arr1', JSON.stringify(arrList2));
            renderFinished();
            renderUnfinished();
            alert('滴滴,时间到');
            clearInterval(time);
          }
        }, 1000)
      }
    })
  }

  // 更新未完成
  function renderUnfinished() {
    let un_ul = document.querySelector(`.note:nth-child(${dataId}) .uul-unfinished`);
    // if (!un_ul) {
    //   console.error('Element .note:nth-child(${dataId}) .uul-unfinished is not found.');
    //   return
    // }
    const listItems = JSON.parse(localStorage.getItem('arr'))[dataId - 1].map((taskText, index) => {
      return `
      <li>
        <a href="#" class="task-icon finished" data-name="${index}"></a>
        <div class="center-item">${taskText}</div>
        <div class="timing">
          定时
          <select data-name="${index}" id="timing-list" class="timeNum">
            <option value="0">0min</option>
            <option value="1">1min</option>
            <option value="2">2min</option>
            <option value="3">3min</option>
            <option value="4">4min</option>
            <option value="5">5min</option>
          </select>
        </div>
        <div class="delete task-icon" data-id="${index}"></div>
      </li>
    `
    }).join('')
    console.log(JSON.parse(localStorage.getItem('arr'))[dataId - 1])
    un_ul.innerHTML = listItems
  }

  // 更新已完成
  function renderFinished() {
    let ul = document.querySelector(`.note:nth-child(${dataId}) .uul-finished`)
    // if (!ul) {
    //   console.error('Element .note:nth-child(${dataId}) .uul-finished is not found.')
    //   return
    // }

    const listItems = JSON.parse(localStorage.getItem('arr1'))[dataId - 1].map((taskText, index) => {
      return `
      <li>
        <a href="#" class="task-icon finished"  data-name="${index}"></a>
        <div class="center-item">${taskText}</div>
        <div class="timing">
          定时
          <select data-name="${index}" id="timing-list" class="timeNum">
            <option value="0">0min</option>
          </select>
        </div>
        <div class="delete task-icon" data-id="${index}"></div>
      </li>
    `
    }).join('')

    ul.innerHTML = listItems
  }


  // 显示当前时间
  function showTime() {

    let date = new Date()

    // 年月日
    let year = date.getFullYear()
    let month = date.getMonth() + 1
    let day = date.getDate()

    // 时分秒
    let hour = date.getHours()
    hour = hour < 10 ? '0' + hour : hour
    let minute = date.getMinutes()
    minute = minute < 10 ? '0' + minute : minute
    let second = date.getSeconds()
    second = second < 10 ? '0' + second : second

    // 显示
    let element = document.getElementById('date')
    element.innerHTML = '<p>' + year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second + '</p>'
  }

  let ShowTime = window.setInterval(showTime, 1000)

  // 初始化事件监听器
  bindEventListeners()

})




到这里就讲完了,感谢大家的观看,希望大家有所收获

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2046578.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三维点云深度网络 PointNeXt 源码阅读 (IV) —— PointNeXt-B

Title: 三维点云深度网络 PointNeXt 源码阅读 (IV) —— PointNeXt-B 文章目录 I. PointNeXt-B 与其他版本的区别II. PointNeXt-B 自动生成的网络III. PointNeXt-B 编码部分的结构IV. 显存溢出的规避总结 关联博文 [1] 三维点云深度网络 PointNeXt 的安装配置与测试 [2] 三维点…

Spring IOC 小演示

首先建项目&#xff0c;可参考 https://blog.csdn.net/2303_79008526/article/details/141141114?spm1001.2014.3001.5502 一、spring 环境搭建 &#xff08;一&#xff09;导相关坐标 <?xml version"1.0" encoding"UTF-8"?> <project xmln…

高通AI-让AI触手可及

生成式AI模型&#xff0c;例如大语言模型和大视觉模型&#xff0c;需要大量的计算资源进行推理&#xff0c;这对于传统的CPU和GPU等通用处理器来说是一个挑战。 1 NPU和异构计算的优势 NPU (神经网络处理器): 专门为AI推理设计的处理器&#xff0c;具有高性能、低功耗的特点&…

Eval绕过限制参数限制

PHP Eval函数参数限制在16个字符 PHP代码 <?php$param $_REQUEST[param]; if (strlen($param) < 17 && stripos($param, eval) false && stripos($param, assert) false){eval($param);}?># 部署环境属于ubuntu系统 通过GET传参绕过 由于是…

贪吃蛇+SDL2库【1】(c语言)

小白的学习记录 一、前置知识 注&#xff1a;博主是小白&#xff0c;所以记录的可能是一些无意中看到&#xff0c;但是不清楚的东西&#xff0c;所以大家择需了解。 JSON JSON&#xff08;JavaScript Object Notation&#xff09; 是一种轻量级的数据交换格式&#xff0c;易于…

10690 分面包

### 伪代码 1. 读取输入的 n 和 m&#xff0c;以及 m 个面包的长度 L。 2. 定义一个函数 canDivide(length)&#xff0c;判断是否可以将所有面包分成每人 length 长度的面包。 3. 使用二分法查找每人分得的最长面包长度&#xff1a; - 初始化 low 为 0&#xff0c;high 为所…

前端工程化-04.Vue项目简介

一.Vue项目-创建 1.使用如图两种方式创建Vue项目 2.在此创建新项目 点击创建项目 创建成功&#xff01; 二.Vue项目-目录结构 三.Vue项目-运行 启动后直接在下方找到连接端口 成功启动项目 这个项目即为Vue中的自带项目Vue.app。修改其中的Home为Vue Home。ctals保存发…

数学建模预测类—【一元线性回归】

每日格言&#xff1a;行动是治愈恐惧的良药&#xff0c;而犹豫拖延将不断滋养恐惧. 目录 前言 一、什么是回归分析&#xff1f; 1.概念理解 2.分类和一般步骤 二、一元线性回归&#xff08;Matlab算法&#xff09; 1.利用regress函数 2、例题讲解 总结 前言 在具体讲述线性回归…

如何在 Windows 10 中配置住宅 IP

什么是住宅IP 住宅IP指的是普通家庭网络的 IP 地址。你可以这样想&#xff1a; IP地址&#xff1a;每一个接入互联网的设备都有一个唯一的“地址”&#xff0c;就像每栋房子都有一个唯一的门牌号一样&#xff0c;这个地址就是IP地址。 住宅IP&#xff1a;指的是那些来自家庭用…

vue2父组件向子孙组件响应式传参,provide/inject响应式

provide和inject一起使用&#xff0c;实现将父组件的数据、方法提供给子孙组件使用&#xff0c;不论组件层次有多深。provide和inject绑定并不是可响应的。但如果你传入了一个可监听的对象&#xff0c;那么其对象的property还是可响应的。 API — Vue.js (vuejs.org)https://v…

完美解决html2canvas + jsPDF导出pdf分页内容截断问题

代码地址&#xff1a;https://github.com/HFQ12333/export-pdf.git html2canvas jspdf方案是前端实现页面打印的一种常用方案&#xff0c;但是在实践过程中&#xff0c;遇到的最大问题就是分页截断的问题&#xff1a;当页面元素超过一页A4纸的时候&#xff0c;连续的页面就会…

基于c++的yolov5推理之后处理详解及代码(二)

目录 一、解析yolov5的输出结果 1、对1*25200*85的向量进行解析 2、预测框中心&#xff08;x&#xff0c;y&#xff09;&#xff0c;预测框的高和宽&#xff08;h&#xff0c;w&#xff09;详解 3、解析代码&#xff1a; 二、confidence过滤 1、confidence计算 三、Non-Maxi…

C++笔记-sstream的使用(字符串转其他类型,读取文件时用得多)

在 C 中&#xff0c;std::stringstream 类可以用来进行字符串流的输入输出&#xff0c;将字符串和其他类型的数据进行转换。 #include <iostream> #include <sstream>int main() {// 将整数转换为字符串int num 123;std::stringstream ss;ss << num;std::s…

单元训练10:定时器实现秒表功能-数组方式

蓝桥杯 小蜜蜂 单元训练10&#xff1a;定时器实现秒表功能-数组方式 /** Description:* Author: fdzhang* Email: zfdcqq.com* Date: 2024-08-15 21:58:53* LastEditTime: 2024-08-16 19:07:27* LastEditors: fdzhang*/#include "stc15f2k60s2.h"#define LED(x) …

火语言RPA--手机对象元素库使用方法

使用自动选取工具获得手机中元素的xpath路径。 工具标识 手机 分组下组件若有此标识&#xff0c;则包含选择元素工具&#xff0c;点击此标识会可以选择手机中的元素进行操作。 元素库介绍 ① 根据元素名称筛选元素库中保存的元素 ② 元素库&#xff0c;显示已经保存的元素名称…

算法的学习笔记—链表中倒数第 K 个结点(牛客JZ22)

&#x1f600;前言 在编程过程中&#xff0c;链表是一种常见的数据结构&#xff0c;它能够高效地进行插入和删除操作。然而&#xff0c;遍历链表并找到特定节点是一个典型的挑战&#xff0c;尤其是当我们需要找到链表中倒数第 K 个节点时。本文将详细介绍如何使用双指针技术来解…

48天笔试训练错题——day47

目录 选择题 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 编程题 1. 合唱团 2. 马戏团 选择题 1. 子网掩码是 255.255.255.0&#xff0c;前三个字节都是 1&#xff0c;则表示有 24 位网络号和子网号。又是 B 类 IP 地址&#xff0c;只有 16 位网络号&#xff0c;所有第三个…

聊聊JS中的WebSocket

你好&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏和关注。个人知乎 在JavaScript中&#xff0c;使用WebSocket非常简单直观。通过几行代码&#xff0c;你就可以轻松创建一个WebSocket连接&#xff0c;并监听来自服务器的消息。无论是开发实时聊天应用、在线游戏、实时数据分…

高效录制新选择:2024年Windows录屏软件

录屏能帮助我们捕捉屏幕上的精彩瞬间&#xff0c;作为老师可以用来录制课程&#xff0c;作为会议记录员可以用来录制远程会议。那么有什么软件是适合windows录屏的呢&#xff1f;这次我们一起来探讨一下吧。 1.福昕录屏大师 链接&#xff1a;www.foxitsoftware.cn/REC/ 这款软…

【数据结构】 顺序表的应用 - 通讯录的实现

0. 前言 上一期博客中&#xff0c;我们已经学习了顺序表是什么&#xff0c;以及顺序表相关接口的实现&#xff0c;了解了如何实现顺序表的插入和删除等功能&#xff0c;那么在这期博客&#xff0c;我们可以基于顺序表来实现一个通讯录&#xff0c;在通讯录当中能实现联系人的增…