```
<template> <div class="todo"> <div class="header"> <span>length </span> <input type="text" @keydown.enter="addTodo" autofocus v-model="newTodo"> <button @click="addTodo">add</button> </div> <hr> <ul class="list"> <!--completed:item.completed item.completed是true的时候,返回class--> <!--item==editedTodo 返回的是true或false , editing 指向的是 class--> <li v-for="(item,index) in todos" :key="index" :class="{completed:item.completed , editing:item==editedTodo}"> <div class="view"> <!--id 号--> <span>{{item.id}}</span> / <!--checkbox 单选框--> <input type="checkbox" v-model="item.completed"> <!--双击的时候--> <label :class="{completed:item.completed}" @dblclick="dbClickEditToDo(item)">{{item.title}}</label> <!--删除的时候--> <span @click="removeTodo(index)">X</span> </div> <!--@blur事件 离开输入框的时候,点击别的地方--> <input type="text" class="edit" v-model="item.title" @blur="doneEditTodo(item)" @keydown.enter="doneEditTodo(item)" /> </li> </ul> <hr> <!--<button--> <!--@click="visibility='all'"--> <!--:class="{selected:visibility=='all'}">all</button>--> <!--<button--> <!--@click="visibility='active'" :class="{selected:visibility=='active'}">active</button>--> <!--<button--> <!--@click="visibility='completed'" :class="{selected:visibility=='completed'}">completed</button>--> </div> </template> <script> let db_name='todo_storage'; export default { data(){ return{ newTodo:'', editedTodo:null, //默认是全部all默认情况下全部显示的; visibility:'all', todos:[ { id:0, title:'hello', completed:false } ] } }, created(){ // 浏览器的localstorage的数据是字符串类型,在这里我处理的话,先把字符串转换成json对象; //这里 setItem的数据浏览器自动渲染的时候不能要刷新; //所以浏览器渲染的时候 this.todos 重新接受localstoraget的数据 this.todos = JSON.parse(window.localStorage.getItem(db_name)||'[]'); }, methods:{ addTodo(){ this.todos.push({ id:this.todos.length, title:this.newTodo, completed:false }); this.newTodo=''; //浏览器存储也是一个数据库,db_name代表数据库的名字,this.todos是推送的数据 window.localStorage.setItem(db_name,JSON.stringify(this.todos)) }, removeTodo(index){ this.todos.splice(index,1); //返回的时删除后的数组 window.localStorage.setItem(db_name,JSON.stringify(this.todos)) }, dbClickEditToDo(todo){ console.log(todo); //双点击的时候,赋值点击的todo , 作用是显示editing class this.editedTodo=todo; }, doneEditTodo(todo){ //如果不存在 , 不存在 edingting class if(!this.editedTodo){ return; } this.editedTodo=null; todo.title=todo.title.trim(); //如果todo的title不存在 , 去掉这个todo内容 if(!todo.title){ this.removeTodo(todo); } //内容编辑操作完成之后,重新处理localstorage window.localStorage.setItem(db_name,JSON.stringify(this.todos)) } } } </script> <style> .header{ margin-bottom: 50px; } .completed{ color: red; font-weight: bold; font-size: 20px; } .list label{ padding: 20px; } .editing{ border-bottom: 0; padding: 0; } .list li .edit{ display: none; } .editing .edit{ display: block!important; width: 200px; padding: 13px 17px 12px 17px; margin:5px 43px; } .list li .completed{ color: green; font-size: 25px; text-decoration: line-through; font-weight: bold; } </style>
```