效果如下:
实现代码:
HTML部分:
<div id="todo" class="todo"> <div class="header"> <section> <!-- input部分 --> <label for="title">ToDoList</label> <input type="text" name="title" placeholder="请输入您的待办事项........." required="required" autocomplete="off" v-model="title" v-on:keypress.enter="addTodo"> </section> </div> <section> <!-- 上半部分 --> <h2>上半部分<span id="todoCount" class="count">{{firstList.length}}</span></h2> <ol id="todoList"> <li v-for="(item,index) in firstList"> <input type="checkbox" v-on:click.prevent="checkedTodo(index)" v-model="item.done"> <p>{{item.title}}</p> <a href="###" v-on:click="deleteABtn1(index)">-</a> </li> </ol> <!-- 下半部分 --> <h2>下半部分<span id="doneCount" class="count">{{doneList.length}}</span></h2> <ol id="doneList"> <li v-for="(item,index) in doneList"> <input type="checkbox" v-on:click.prevent="checkedDone(index)" v-model="item.done"> <p>{{item.title}}</p> <a href="###" v-on:click="deleteABtn2(index)">-</a> </li> </ol> </section> <p class="footer">footer</p> </div>
CSS部分:
* { margin: 0; padding: 0; } body { font-size: 16px; background: #cdcdcd; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } .header { height: 50px; background: rgba(47, 47, 47, 0.98); } section { max-width: 620px; margin: 0 auto; padding: 0 10px; } label { float: left; width: 100px; line-height: 50px; color: #ddd; font-size: 24px; cursor: pointer; } .header input { float: right; width: 60%; height: 24px; margin-top: 12px; text-indent: 10px; border-top-left-radius: 5px; border-radius: 5px; box-shadow: 0 1px 0 rgba(255, 255, 255, 0.24), 0 1px 6px rgba(0, 0, 0, 0.45) inset; outline: none; border: none; } h2 { position: relative; margin: 26px 0; } h2 .count { 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 { margin: 28px 0 32px; } ol, ul { list-style-type: none; } li { height: 32px; line-height: 32px; background: #fff; position: relative; margin-bottom: 10px; padding: 0 48px; border-radius: 3px; border-left: 5px solid #629a9c; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07); } li input { position: absolute; top: 6px; left: 22px; width: 22px; height: 22px; cursor: pointer; } li p { line-height: 34px; } li a { position: absolute; top: 4px; right: 5px; display: inline-block; width: 14px; height: 12px; border-radius: 14px; border: 6px double #fff; background: #ccc; line-height: 12px; text-align: center; color: #fff; font-weight: bold; font-size: 14px; cursor: pointer; } #doneList li { border-left: 5px solid #999; opacity: 0.5; } .footer { font-size: 14px; text-align: center; color: #666; } @media only screen and (max-width: 400px){ .header input{ width: 52%; } }
script部分:
var todo = new Vue({ el: "#todo", data: { title: '', // 设置firstList为空数组 firstList: [], // 设置doneList为空数组用来存放到本地 doneList: [], }, // 载入前: beforeMount() { // 加载localstorage var storage = window.localStorage; // 如果获取的todo不为空值时 if (storage.getItem("todo") !== null) { // 从字符串中解析json对象,并获取数据todo this.firstList = JSON.parse(storage.getItem("todo")); } if (storage.getItem("done") !== null) { this.doneList = JSON.parse(storage.getItem("done")); } }, methods: { // 当点击后触发 addTodo() { // 如果input框里为空则跳出弹窗 if (this.title === '') { return alert('您尚未输入需要存储的数据!!'); } // 如果有东西那么 上半部分的span中的数值就会将获取到的新数据放在数组的第一个位置 this.firstList.unshift({ // 让input中的title进行绑定 title: this.title, // 把done按钮设置为关闭状态 done: false }); // 输入完毕后记得清空input框里的值 this.title = ''; // 把数据存储到本地 this.setLocalStorage(); }, // 当点击第一部分的删除按钮a时触发该事件 deleteABtn1(index) { // 把存储过的值进行删除 this.firstList.splice(index, 1); // 删除完毕后把剩下的存储到本地 this.setLocalStorage(); }, // 当点击第二部分的删除按钮a时触发事件 deleteABtn2(index) { // 点击后可以删除对应的部分 this.doneList.splice(index, 1); // 存储一下 this.setLocalStorage(); }, // 点击第一部分中的input时触发事件 checkedTodo(index) { // span中的数字的索引的done就为true // firstList.children[0].checked = 'checked' this.firstList[index].done = true; // 把firstList放在doneList的最前面 this.doneList.unshift(this.firstList[index]); // 然后上半部分的span的索引也对应删除 this.firstList.splice(index, 1); // 并进行存储 this.setLocalStorage(); }, // 当下半部分出现后的input框(也就是被勾选的框中) 对其设置点击事件 // 主要是实现点击后将复选框变为关闭状态,并且放在上半部分里,删除本身所在的位置 checkedDone(index) { // 下半部分的span数字的索引done值设置为flase this.doneList[index].done = false; // 把下半部分放在上半部分大的最前面 this.firstList.unshift(this.doneList[index]); // 下半部分的span点击后将删除当前的值 this.doneList.splice(index, 1); this.setLocalStorage(); }, setLocalStorage() { // 存储localstorage var storage = window.localStorage; // 将 JavaScript 值转换为 JSON 字符串 storage.setItem("todo", JSON.stringify(this.firstList)); storage.setItem("done", JSON.stringify(this.doneList)); } } });