一,demo背景:

  • 1,可以熟悉原生js

  • 2,平时不知道自己学完js要做些什么东西的小伙伴

  • 3,自己写的,可以当做自己的作品

  • 4,为广大想练习练习原生js的贡献一个素材

二,实现功能:

  • 1,新建/删除任务功能

  • 2,设置/取消星标任务功能

  • 3,设置/取消任务完成功能

  • 4,过期任务自动删除功能(本例期限设置为了2天)

  • 5,任务超时后禁止操作功能

三, 逻辑实现:

把新建的一个任务就抽象成一个对象,该对象里面有自己的创建时间,内容,结束事件,是否为星标任务等等。然后这个对象字符串化存放到localStorage里,每次在要数据时,都从localStorage里面取出数据。最后就是用各种的数据进行If..else判断,渲染Dom。(过程中用到了很多字符串,数组方法,可以增加你对这些方法的熟练度)

四,demo效果展示:

完成了的任务:

图片描述

星标任务:

图片描述

五,代码展示:

html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>LocalNotepad</title>
    <link rel="stylesheet" type="text/css" href="font-awesome-4.5.0/css/font-awesome.css">
    <link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div id="m-hidden"></div>
<div id="pub-box">
    <textarea class="content" placeholder="为你添加新的任务"></textarea>
    <div class="but-box">
        <div class="time-box">
            <p class="static">任务起始时间 :</p>
            <p class="time-begin">
                <input type="text" class="t-b-year" placeholder=""><time>年</time>
                <input type="text" class="t-b-mon" placeholder=""><time>月</time>
                <input type="text" class="t-b-day" placeholder=""><time>日</time>
            </p>
            <p class="static">务结束时间 :</p>
            <p class="time-end">
                <input type="text" class="t-b-year"><time>年</time>
                <input type="text" class="t-b-mon"><time>月</time>
                <input type="text" class="t-b-day"><time>日</time>
            </p>
        </div>
        <div class="btn">
            <button class="reset">重置</button>
            <button class="add">添加</button>
        </div>
    </div>
</div>
<div id="content">
</div>
<script type="text/javascript" src="js/Tool.js"></script>
<script type="text/javascript" src="js/script.js"></script>
</body>
</html>

css:

* {
    margin: 0;
    padding: 0;
    font-family: "Microsoft YaHei"
}
html,body {
    height: 100%;
}
body {
    background: #fafc2a;
    background: url('../images/1.jpg') no-repeat 0 -50px;
    background-size: 100%;
    background-attachment: fixed;
}
a {text-decotation: none;}
strong {font-weight: normal;}
i,b {font-style: none;}

/*样式开始*/
#m-hidden {
    height: 1px;
    background: transparent;
}
#pub-box {
    width: 1000px;
    height: 220px;
    background: rgba(0, 0, 0, 0.5);
    box-sizing: border-box;
    margin: 0 auto;
    padding: 20px;
    margin-top: -140px;
    transition: .6s;
}
#pub-box:hover {
    margin-top: -1px;
    transition: .6s;
}
#pub-box .content {
    width: 100%;
    height: 120px;
    background: rgba(246, 248, 41, 0.5);
    resize: none;
    outline: none;
    border: none;
    box-sizing: border-box;
    padding: 10px;
}
#pub-box .but-box:after {
    content:'';
    display: block;
    width: 0;
    height: 0;
    clear: both;
}
#pub-box .but-box .time-box{
    float: left;
}
#pub-box .but-box .time-box:after {
    content:'';
    display: block;
    width: 0;
    height: 0;
    clear: both;
}
#pub-box .but-box .time-box p {
    float: left;
    margin-top: 25px;
    color: #fafc2a;
}
#pub-box .but-box .time-box .time-begin{}
#pub-box .but-box .time-box .time-end{}
#pub-box .but-box .time-box .time-begin,
#pub-box .but-box .time-box .time-end {
    margin-right: 30px;
}
#pub-box .but-box .time-box .time-begin input,
#pub-box .but-box .time-box .time-end input,
#pub-box .but-box .time-box .time-begin time,
#pub-box .but-box .time-box .time-end time {
    float: left;
    margin: 0 3px;
}
#pub-box .but-box .time-box .time-begin input,
#pub-box .but-box .time-box .time-end input {
    display: block;
    width: 40px;
    height: 22px;
    text-align: center;
    outline: none;
    background: rgba(246, 248, 41, 0.3);
    border: none;
    color: #000;
}
#pub-box .but-box .btn {
    float: right;
}
#pub-box .but-box button {
    display: block;
    float: right;
    width: 70px;
    height: 30px;
    outline: none;
    border: none;
    margin-top: 20px;
    margin-left: 20px;
    letter-spacing: 2px;
    background: #fafc2a;
    color: #000;
}
#pub-box .but-box button:hover {
    background: #f8fa5b;
    color: #555;
}
#content {
    width: 1000px;
    height: auto;
    margin: 50px auto 0 auto;
}
#content .c-b{
    position: relative;
    width: 100%;
    background: rgba(0, 0, 0, 0.5);
    margin-bottom: 20px;
    box-sizing: border-box;
    padding: 20px;
    color: #fafc2a;
}
#content .red-star {
    position: absolute;
    width: 20px;
    height: 20px;
    top: 0px;
    left: 0px;
    text-align: center;
    line-height: 23px;
}
#content .fa-star {
    color: #fafc2a;
}
#content .ms-cont-b {
    width: 100%;
}
#content .ms-cont-b:after {
    content:'';
    display: block;
    width: 0;
    height: 0;
    clear: both;
}
#content .ms-cont-b .ms-cont {
    float: left;
    max-width: 700px;
    word-break: break-all;
    font-size: 18px;
    letter-spacing: 1px;
}
#content .ms-icon {
    float: right;
    width: 80px;
    height: 80px;
    text-align: center;
    font-size: 80px;
    line-height: 80px;
    /*color: #d71d2e;*/
    color: #fafc2a;
}
#content .ms-b {
    width: 100%;
    margin-top: 20px;
}
#content .ms-b:after {
    content:'';
    display: block;
    width: 0;
    height: 0;
    clear: both;
}
#content .ms-b .ms-time {
    width: 600px;
    float: left;
    margin-top: 25px;
}
#content .ms-b .ms-time:after{
    content:'';
    display: block;
    width: 0;
    height: 0;
    clear: both;
}
#content .ms-b .ms-btn {
    float: right;
    // display: none;
}
#content .ms-b .ms-time .create-t {
    float: left;
}
#content .ms-b .ms-time .set-t{
    float:left;
    margin-left: 50px;
}
#content .ms-b .ms-btn button{
    display: block;
    float: right;
    width: 70px;
    height: 30px;
    outline: none;
    border: none;
    margin-top: 20px;
    margin-left: 20px;
    letter-spacing: 2px;
}
#content .ms-b .ms-btn button.star {
    width: 120px;
    background: #fafc2a;
    color: #000;
}
#content .ms-b .ms-btn button.del {
    background: #fafc2a;
    color: #000;
}
#content .ms-b .ms-btn button.finished {
    width: 100px;
    background: #fafc2a;
    color: #000;
}
#content .ms-b .ms-btn button.del:hover {
    background: #f0f204;
}
#content .ms-b .ms-btn button.star:hover {
    background: #f0f204;
}
#content .ms-b .ms-btn button.finished:hover {
    background: #f0f204;
}

js:

(function() {
  var textContent = document.querySelector('#pub-box .content'),
      beginTimes = document.querySelectorAll('#pub-box .time-begin input'),
      endTimes = document.querySelectorAll('#pub-box .time-end input'),
      reset = document.querySelector('#pub-box .btn .reset'),
      add = document.querySelector('#pub-box .btn .add'),
      content = document.querySelector('#content'),
      temp = localStorage.getItem('D'),
      id,
      data,
      lcdata;
      
  if (!temp) {
    data = [];
  } else {
    data = JSON.parse(temp);
  }

  /*插入任务*/
  function createAriticle(id, text, createTime, msTime) {
    var str = '<article class="c-b" data-id="' + id + '">' +
                '<div class="red-star"></div>' +
                '<div class="ms-cont-b">' +
                    '<div class="ms-cont">' + text + '</div>' +
                    '<div class="ms-icon"></div>' + 
                '</div>' + 
                '<div class="ms-b">' +
                    '<div class="ms-time">' +
                        '<p class="create-t">创建于:<span>' + createTime + '</span></p>' +
                        '<p class="set-t">' + msTime +'</p>' +
                    '</div>' +
                    '<div class="ms-btn">' +
                        '<button class="del" onclick="deletArticle(this)">删除</button>' +
                        '<button class="star" onclick="addRedStar(this)">设为星标任务</button>' +
                        '<button class="finished" onclick="isFinish(this)">确认完成</button>' +
                    '</div>' +
                '</div>' +
            '</article>'
    content.innerHTML = str + content.innerHTML;
  }
  /*删除任务*/
  function deletArticle(self) {
    var id = self.parentNode.parentNode.parentNode.getAttribute('data-id');
    var parent = self.parentNode.parentNode.parentNode.parentNode;
    var arts = document.querySelectorAll('.c-b');
    var s;
    for (var i = 0; i < arts.length; i++) {
      if (arts[i].getAttribute('data-id') == id) {
        parent.removeChild(arts[i]);
        for (var j = 0; j < data.length; j++) {
          if (data[j].id == id) {
            data.splice(j,1);
          }
        }
      }
    }
    s = JSON.stringify(data);
    localStorage.setItem('D', s);
  }
  window.deletArticle = deletArticle;
  /*添加星标任务*/
  function addRedStar(self) {
    var id = self.parentNode.parentNode.parentNode.getAttribute('data-id');
    var str;
    for (var i = 0; i < data.length; i++) {
      if (data[i].id == id) {
        if (!data[i].star) {
          self.parentNode.parentNode.parentNode.children[0].className = 'red-star fa fa-star';
          self.innerHTML = "取消星标任务";
          data[i].star = true;
        } else {
          self.parentNode.parentNode.parentNode.children[0].className = 'red-star';
          self.innerHTML = "设为星标任务";
          data[i].star = false;
        }
      }
    }
    str = JSON.stringify(data);
    localStorage.setItem('D', str);
  }
  window.addRedStar = addRedStar;
 /*确认任务完成操作*/
  function isFinish(self) {
    var id = self.parentNode.parentNode.parentNode.getAttribute('data-id');
    var str;
    for (var i = 0; i < data.length; i++) {
      if (data[i].id == id) {
        if (data[i].finished == 0) {
          self.parentNode.parentNode.previousSibling.children[1].className = 'ms-icon fa fa-check';
          self.innerHTML = "取消完成";
          data[i].finished = 1;
        } else if (data[i].finished == 1) {
          self.parentNode.parentNode.previousSibling.children[1].className = 'ms-icon';
          self.innerHTML = "确认完成";
          data[i].finished = 0;
        } else {
          return;
        }
      }
    }
    str = JSON.stringify(data);
    localStorage.setItem('D', str);
  }
  window.isFinish = isFinish;
  /*页面加载完,向页面加载默认任务起始时间*/
  function addDefaultTime() {
    var date = new Date();
    beginTimes[0].placeholder = date.getFullYear();
    beginTimes[1].placeholder = date.getMonth() + 1;
    beginTimes[2].placeholder = date.getDate();
  }
  addDefaultTime();
  /*加载任务*/
  function loadThing() {
    var arr,
        length,
        sets,
        finishs,
        arts,
        stars,
        now = new Date().getTime(),
        d = localStorage.getItem('D');
    if (!d) {
      console.log(d);
      return;
    }
    arr = JSON.parse(d);
    length = arr.length;
    for (var m = 0; m < length; m++) {
      if ((now - arr[m].id) > 259200000) {
        arr.splice(m, 1);
      }
    }
    if (!arr.length) {
      return;
    }
    for (var i = 0; i < length; i++) {
      createAriticle(arr[i].id, arr[i].text, arr[i].createTime, arr[i].msTime);
    }
    arts = document.querySelectorAll('.c-b');
    finishs = document.querySelectorAll('.finished');
    for (var i = 0; i < length; i++) {
      if (arr[i].star) {
        for (var j = 0; j < arts.length; j++) {
          if (arts[j].getAttribute('data-id') == arr[i].id) {
            arts[j].children[0].className = 'red-star fa fa-star';
            arts[j].getElementsByClassName('star')[0].innerHTML = '取消星标任务';
          }
        }
      }
      if ((arr[i].em - arr[i].bm) < 0) {
        arr[i].finished = 2;
      } 
      if (arr[i].finished == 0) {
        for (var k = 0; k < arts.length; k++) {
          if (arts[k].getAttribute('data-id') == arr[i].id) {
            arts[k].getElementsByClassName('ms-icon')[0].className = 'ms-icon';
            arts[k].getElementsByClassName('finished')[0].innerHTML = '确认完成';
          }
        }
      } else if (arr[i].finished == 1) {
        for (var t = 0; t < arts.length; t++) {
          if (arts[t].getAttribute('data-id') == arr[i].id) {
            arts[t].getElementsByClassName('ms-icon')[0].className = 'ms-icon fa fa-check';
            arts[t].getElementsByClassName('finished')[0].innerHTML = '取消完成';
          }
        }
      } else if (arr[i].finished == 2) {
        for (var n = 0; n < arts.length; n++) {
          if (arts[n].getAttribute('data-id') == arr[i].id) {
            arts[n].getElementsByClassName('ms-icon')[0].className = 'ms-icon fa fa-close';
            arts[n].getElementsByClassName('finished')[0].style.display = 'none';
            arts[n].getElementsByClassName('star')[0].style.display = 'none';
          }
        }
      }
    }
  }
  loadThing();
  /*重置按钮*/
  function resetContent() {
    var length = endTimes.length;
    textContent.value = "";
    for (var i = 0; i < length; i++) {
      beginTimes[i].value = "";
      endTimes[i].value = "";
    }
  }
  reset.addEventListener('click', function(ev){
    var ev = ev || event;
    ev.stopPropagation();
    resetContent();
  }, false);
  /*添加任务*/
  add.addEventListener('click', function(ev){
    var ev = ev || event;
    ev.stopPropagation();
    var date = new Date(); 
    var createTime,
        beginTime,
        contText,
        endTime,
        defY,
        defM,
        defD, 
        msTime,
        em,
        bm,
        c,
        id = new Date().getTime();
    if (textContent.value == "") {
      alert('输入不能为空');
      return;
    }
    if (endTimes[0].value == "" || endTimes[1].value == "" || endTimes[2].value == "") {
      alert('结束时间不能留空');
      return;
    }  
    if (beginTimes[0].value == "") {
      defY = beginTimes[0].placeholder;
    } else {
      defY = beginTimes[0].value;
    }
    if (beginTimes[1].value == "") {
      defM = beginTimes[1].placeholder;
    } else {
      defM = beginTimes[1].value;
    }
    if (beginTimes[2].value == "") {
      defD = beginTimes[2].placeholder;
    } else {
      defD = beginTimes[2].value;
    }
    c = id - new Date(date.getFullYear() + '/' + (date.getMonth() + 1) + '/' + date.getDate()).getTime();
    createTime = date.getFullYear() + '年' +
                  (date.getMonth() + 1) + '月' +
                  date.getDate() + '日';

    endTime = {
      year: endTimes[0].value,
      month: endTimes[1].value,
      day: endTimes[2].value
    }
    em = new Date(endTime.year + '/' + endTime.month + '/' + endTime.day).getTime() + c;
    beginTime = {
      year: defY,
      month: defM,
      day: defD
    }
    bm = new Date(beginTime.year + '/' + beginTime.month + '/' + beginTime.day).getTime() + c;
    msTime = '任务有效期:' + beginTime.year + '年' + beginTime.month + '月' + 
              beginTime.day + '日  至 ' + endTime.year + '年' + endTime.month + '月' + 
              endTime.day + '日';
    /*一个文章的整体数据*/
    var contText = {
      text: textContent.value,
      createTime: createTime,
      beginTime: beginTime,
      endTime: endTime,
      star: false,
      finished: 0,
      msTime: msTime,
      id: id,
      bm: bm,
      em: em
    }
    data.push(contText);
    lcdata = JSON.stringify(data);
    localStorage.setItem('D', lcdata);
    createAriticle(contText.id, contText.text, contText.createTime, contText.msTime);
    resetContent();
  }, false);
})()

六,不足之处:

1,在输入日期的时候没有过滤掉非法日期,这里最好能用一个日历组件进行选择日期,能保证日期的准确性。否则任务的完成时间会出错,导致页面渲染错误。(组件正在开发中,后期会分享)
2,缺少弹窗提示,这里的操作动作很多,完全可以开发一个弹窗组件,方便用。体验比较好。(组件正在开发中,后期会分享)
3,创建后的任务不能更改任务内容是个缺陷。

demo分享到此结束,笔者有什么地方错误或者理解不到位的地方还请大家指出来。


风再起时
125 声望8 粉丝

喜欢简单干净的事物!