我是靠谱客的博主 老迟到宝马,最近开发中收集的这篇文章主要介绍JavaScript+HTML5+CSS3完美实现ToDoList(详细注释),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

JavaScript+HTML5+CSS3完美实现ToDoList

实现目标:
实现在todolist中添加未完成事件,事件完成后点击checkbox多选框可以将该事件移入donelist列表中,双击事件名称可更改事件名称,点击“-”实现删除该事件,点击清空可清除全部事件,利用localStorsge实现本地长期存储,关闭浏览器再次打开浏览器可直接显示上次对该页面最后操作所显示的样式。

整体思路
1、title中输入事件,点击回车后添加到未完成事件todolist列表中
2、点击todolist列表中未完成事件的多选框会添加到donelist中
3、点击事件后面的删除会将该事件在对应列表中删除
4、双击todolist中的事件可以更改事件名称,失焦后确认更改
5、每次渲染之前都将信息保存到localStorage中,下次打开时判断是否有该属性,如果有直接判断
6、在每次操作后重新渲染dom
7、当点击clear时清空所有事件列表清空localStorage

css样式在文章最下方

html+js代码部分

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link href="./css/main.css" rel="stylesheet" />
  </head>
  <body>
    <header>
      <section>
        <div id="form">
          <label for="title">ToDoList</label>
          <input type="text" id="title" placeholder="添加ToDo" />
        </div>
      </section>
    </header>
    <section>
      <h2>正在进行 <span id="todocount">0</span></h2>
      <ol id="todolist" class="demo-box"></ol>
      <h2>已经完成 <span id="donecount">0</span></h2>
      <ul id="donelist"></ul>
    </section>
    <footer>Copyright © 2014 todolist.cn <a href="#">clear</a></footer>

<script>
  // 整体思路
  // 1、title中输入事件,点击回车后添加到未完成事件todolist列表中
  // 2、点击todolist列表中未完成事件的多选框会添加到donelist中
  // 3、点击事件后面的删除会将该事件在对应列表中删除
  // 4、双击todolist中的事件可以更改事件名称,失焦后确认更改
  // 5、每次渲染之前都将信息保存到localStorage中,下次打开时判断是否有该属性,如果有直接判断
  // 6、在每次操作后重新渲染dom
  // 7、当点击clear时清空所有事件列表清空localStorage

  var title, todolist, donelist, todocount, donecount, prev;
  var list = {
    todolist: [],
    donelist: [],
  };
  init();
  function init() {
    title = document.querySelector("#title");
    todolist = document.querySelector("#todolist");
    donelist = document.querySelector("#donelist");
    todocount = document.querySelector("#todocount");
    donecount = document.querySelector("#donecount");
    // 将清空列表的点击事件委托给父元素footer
    // 将改变事件完成或未完成的点击事件委托给父元素li
    footer=document.querySelector("footer")
    footer.addEventListener("click",clickHandler)
    document.addEventListener("keyup", keyHandler); //输入
    todolist.addEventListener("change", changeHandler); //更改位置
    todolist.addEventListener("click", clickHandler); //删除
    todolist.addEventListener("dblclick", dblClickHandler); //更改名称
    todolist.addEventListener("focusout", blurHandler); //失焦

    donelist.addEventListener("change", changeHandler); //更改位置
    donelist.addEventListener("click", clickHandler); //删除

    // 初始化渲染
    // 如果在localStorage中找到上次保存的信息直接进行初始化渲染
    if (localStorage.list) {
      list = JSON.parse(localStorage.list);
      render();
    }
  }
  // 在title中输入完成按回车并且输入内容不为空时,将输入内容添加到todolist数组保存,并且清空输入框中内容
  // 执行DOM渲染
  function keyHandler(e) {
    if (e.keyCode !== 13 || title.value.trim().length === 0) return;
    list.todolist.push(title.value);
    title.value = "";
    render();
  }
  // 点击todolist或donelist中事件的多选框时进入switchLit函数,将位置转换
  function changeHandler(e) {
    if (e.target.type !== "checkbox") return;
    switchList(e.target, e.target.checked);
  }
  // 带入三个参数,分别为点击的对象,该对象checkbox的选中状态,是否删除该事件
  function switchList(target, bool, remove) {
    // 当前对象是选中状态(在donelist中)或未选中状态(在todolist中)
    // 如果是移动事件就是将该事件从源列表中删除后再添加到另一个列表中
    // 如果有删除参数remove并且为true,则从原列表中删除且不在另一个列表中添加
    var arr = bool
      ? Array.from(todolist.children)
      : Array.from(donelist.children);
    var arr1 = bool
      ? Array.from(donelist.children)
      : Array.from(todolist.children);
    // 判断当前对象是否有删除参数true,如果有则是删除该事件寻找他的上一个兄弟元素(p标签),
    // 如果没有则不是进行删除,只是改变位置,则寻找他的下一个兄弟元素(p标签)
    var elem =
      remove === undefined
        ? target.nextElementSibling
        : target.previousElementSibling;
    // 按照p标签的父元素li查找
    // 避免了使用elem.textConent查找当有重复事件时删除会删除第一个(因为indexOf查找会查找到第一个匹配的就不再往后查找)
    var index = arr.indexOf(elem.parentElement);
    // 查找该事件在对应列表中的下标,将他从原列表中删除,会返回被删除的元素所组成的数组
    var del = (bool ? list.todolist : list.donelist).splice(index, 1);
    // 如果该事件不是删除,则将他添加到另一个列表中
    if (remove === undefined)
      (bool ? list.donelist : list.todolist).push(del[0]);
    // 执行DOM渲染
    render();
  }
  // 如果点击的是A标签且父元素为li,将当前点击元素带入switchList并将remove参数设为true
  function clickHandler(e) {
    if (e.target.nodeName !== "A") return;
    if (e.target.parentElement.nodeName === "LI") {
      switchList(
        e.target,
        !e.target.parentElement.firstElementChild.checked, //为什么取非?
        true
      );
    } else{
      // 如果点击的A标签不是li中的A标签而是footer中的A标签
      // 则清空list中todolist和donelist然后重绘,实现一键清空
      list.todolist.length=0;
      list.donelist.length=0;
      console.log(list)
      render();
    }
  }
  // 双击时实现聚焦选中该文字,将input的双击事件委托给父元素p,
  // 如果prev存在时,将他隐藏
  // 设置当前prev为当前点击p标签内的input
  // 当点击的元素是p标签时,将隐藏的input标签显示出来,将p标签的文字内容赋给他,初始内容为标签原来的文字
  // 并且选中其中内容
  function dblClickHandler(e) {
    if (e.target.nodeName !== "P") return;
    var input = e.target.firstElementChild;
    if (prev) {
      prev.style.display = "none";
    }
    prev = input;
    input.style.display = "block";
    input.value = e.target.textContent;
    input.setSelectionRange(0, input.value.length); //选中文本框字符串
    input.focus(); //聚焦
  }

  // 失焦事件
  // 将todolist下的li转化为数组,查找要更改的p标签属于哪个li,
  // 判断输入内容不为空
  // 更改相应内容为输入框input新输入的内容
  // 重新进行DOM渲染
  function blurHandler(e) {
    var index = Array.from(todolist.children).indexOf(
      e.target.parentElement.parentElement
    );
    if(e.target.value.trim()!=="")
    list.todolist[index] = e.target.value;
    console.log(e.target);
    render();
  }

  // DOM渲染
  function render() {
    // 将添加事件信息添加到localStorage中本地保存
    localStorage.list = JSON.stringify(list);
    for (var prop in list) {
      window[prop].innerHTML = list[prop].reduce((value, item) => {
        return (
          value +
          `
                <li>
                    <input type="checkbox" ${
                      prop === "donelist" ? "checked" : ""
                    }>
                    <p>${item}<input type="text" style="display:none"></p>
                    <a href="javascript:void(0)">-</a>     
                 </li>
                `
        );
      }, "");
    }
    // 更改右上角事件数量显示
    todocount.textContent = list.todolist.length;
    donecount.textContent = list.donelist.length;
  }
</script>

实现效果:
初始状态:初始状态
添加事件:
添加事件
localStorage相应写入
改变事件完成或未完成:
改变事件完成或未完成
改变事件完成或未完成
改变事件名称:
改变事件名称
改变事件名称
删除事件:
删除事件
删除事件
清空事件列表:
清空事件列表
清空事件列表

css代码:

body {
    margin: 0;
    padding: 0;
    font-size: 16px;
    background: #cdcdcd;
  }
  header {
    height: 50px;
    background: #333;
    background: rgba(47, 47, 47, 0.98);
  }
  section {
    margin: 0 auto;
  }
  label {
    float: left;
    width: 100px;
    line-height: 50px;
    color: #ddd;
    font-size: 24px;
    cursor: pointer;
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  }
  header input {
    float: right;
    width: 60%;
    height: 24px;
    margin-top: 12px;
    text-indent: 10px;
    border-radius: 5px;
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.24),
      0 1px 6px rgba(0, 0, 0, 0.45) inset;
    border: none;
  }
  input:focus {
    outline-width: 0;
  }
  h2 {
    position: relative;
  }
  span {
    position: absolute;
    top: 2px;
    right: 5px;
    display: inline-block;
    padding: 0 5px;
    height: 20px;
    border-radius: 20px;
    background: #e6e6fa;
    line-height: 22px;
    text-align: center;
    color: #666;
    font-size: 14px;
  }
  ol,
  ul {
    padding: 0;
    list-style: none;
  }
  li input {
    position: absolute;
    top: 2px;
    left: 10px;
    width: 22px;
    height: 22px;
    cursor: pointer;
  }
  p {
    margin: 0;
    user-select: none;
  }
  li p input {
    top: 3px;
    left: 40px;
    width: 70%;
    height: 20px;
    line-height: 14px;
    text-indent: 5px;
    font-size: 14px;
  }
  li {
    height: 32px;
    line-height: 32px;
    background: #fff;
    position: relative;
    margin-bottom: 10px;
    padding: 0 45px;
    border-radius: 3px;
    border-left: 5px solid #629a9c;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07);
  }
  ol li {
    cursor: move;
  }
  ul li {
    border-left: 5px solid #999;
    opacity: 0.5;
  }
  li a {
    position: absolute;
    top: 2px;
    right: 5px;
    display: inline-block;
    width: 14px;
    height: 12px;
    border-radius: 14px;
    border: 6px double #fff;
    background: #ccc;
    line-height: 14px;
    text-align: center;
    color: #fff;
    font-weight: bold;
    font-size: 14px;
    cursor: pointer;
  }
  footer {
    color: #666;
    font-size: 14px;
    text-align: center;
  }
  footer a {
    color: #666;
    text-decoration: none;
    color: #999;
  }
  @media screen and (max-device-width: 620px) {
    section {
      width: 96%;
      padding: 0 2%;
    }
  }
  @media screen and (min-width: 620px) {
    section {
      width: 600px;
      padding: 0 10px;
    }
  }

最后

以上就是老迟到宝马为你收集整理的JavaScript+HTML5+CSS3完美实现ToDoList(详细注释)的全部内容,希望文章能够帮你解决JavaScript+HTML5+CSS3完美实现ToDoList(详细注释)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(82)

评论列表共有 0 条评论

立即
投稿
返回
顶部