index部分
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" type="text/css" href="css/todolist.css" /> </head> <body> <div id="app"> <header> <form @submit.prevent='submit($event)'> <label for="inpTitle">ToDoList</label> <input type="text" id="inpTitle" placeholder="添加ToDo" required="required" /> </form> </header> <section> <ullist title="正在进行" :local="local" :num="todonum" :flag="todoflag" @dellist="delitem" @editdatalist="editdataitem(arguments)" @changedatalist="changedataitem"></ullist> <ullist title="已完成" :local="local" :num="donenum" :flag="doneflag" @dellist="delitem" @editdatalist="editdataitem(arguments)" @changedatalist="changedataitem"></ullist> </section> <footer> <p>Copyright © 2014 todolist.cn <a @click="clearLocal()">clear</a></p> </footer> </div> <template id="ullist"> <div> <slot> <h2>{{title}}<span>{{num}}</span></h2> <ul> <li v-for="(item,index) in local" :key="index" v-if="item.todo===flag"> <input type="checkbox" @change="changedata(index)" :checked="flag" /> <input type="text" v-model="item.title" @blur="editdata($event,index)" /> <a @click="del(index)">-</a> </li> </ul> </slot> </div> </template> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> <script> const ullist = { template: '#ullist', props: { title: { type: String }, local: { type: Array }, flag: { type: Boolean, default: false }, num: { type: Number, default: 0 } }, methods: { del(index) { this.$emit('dellist', index) }, editdata(e, index) { this.$emit('editdatalist', e, index) }, changedata(index) { this.$emit('changedatalist', index) } } } </script> <script src="js/todolist.js"></script> </body> </html>
css部分:
*{ margin: 0; padding: 0; } a{ text-decoration: none; cursor: pointer; } li{ list-style: none; } body{ background-color: #CDCDCD; } header{ width: 100%; height: 50px; background-color: #323232; } header form{ width: 620px; height: 50px; margin: 0 auto; } form label{ color: #DDDDDD; font-size: 24px; line-height: 50px; cursor: pointer; } form input{ width: 364px; height: 26px; outline: 0; padding-left: 10px; box-sizing: border-box; border-radius: 5px; background-color: #FFFFFF; float: right; margin-top: 12px; border: none; box-shadow: 0 1px 0 rgb(255 255 255 / 24%), 0 1px 6px rgb(0 0 0 / 45%) inset; } section{ width: 620px; padding: 0px 10px; box-sizing: border-box; margin: 0 auto; } section h2{ margin: 20px 0px; } section h2 span{ display: inline-block; height: 20px; line-height: 20px; text-align: center; color: #666666; font-size: 14px; background-color: #E6E6FA; padding: 0px 5px; border-radius: 20px; float: right; margin-top: 6px; } section ul li{ height: 32px; background-color: #FFFFFF; border-left: 5px solid #629A9C; line-height: 32px; margin-bottom: 10px; border-radius: 3px; box-shadow: 0 1px 2px rgb(0 0 0 / 7%); padding: 0px 45px; position: relative; } section ul li p{ margin: 0 auto; height: 32px; } section ul li>input:nth-of-type(1){ width: 22px; height: 22px; position: absolute; top: 50%; left: 12px; margin-top: -11px; } section ul li>input:nth-of-type(2){ width: 100%; height: 90%; box-sizing: border-box; border: none; font-size: 16px; } section ul li>input:nth-of-type(2):focus{ outline: 1px solid #333333; padding-left: 5px; } section ul li a{ display: block; width: 26px; height: 24px; line-height: 12px; text-align: center; box-sizing: border-box; border-radius: 14px; border: 6px double #FFF; background: #CCC; color: #FFFFFF; font-weight: 700; position: absolute; top: 50%; right: 12px; margin-top: -12px; } footer{ color: #666666; font-size: 14px; text-align: center; } footer a{ color: #999999; }
JS部分
const app = new Vue({ el: '#app', data() { return { local: [], todoflag: false, doneflag: true, todonum: 0, donenum: 0 } }, components: { ullist }, methods: { submit(e) { console.log(e.target[0].value); let newtodo = { "title": e.target[0].value, "todo": false } e.target[0].value = '' //点击回车增加数据 this.local.unshift(newtodo) //存储数据 this.savedata() this.count() }, //存储数据 savedata() { window.localStorage.setItem('todo', JSON.stringify(this.local)) }, //删除数据 delitem(index) { //删除点击的某一项 this.local.splice(index, 1) //存储数据 this.savedata() this.count() }, //编辑数据 editdataitem(e) { console.log(e[0]); //代表点击某一项失焦事件 console.log(e[1]); //索引 var index = e[1] this.local[index].title = e[0].target.value //存储数据 this.savedata() }, //切换数据 changedataitem(index) { console.log(index); this.local[index].todo ? this.local[index].todo = false : this.local[index].todo = true, //存储数据 this.savedata() this.count() }, //数据个数 count() { this.donenum = 0; this.todonum = 0; this.local.forEach((v, index) => { v.todo ? this.donenum++ : this.todonum++ }) } }, created() { let data = window.localStorage.getItem('todo') if (data != null) { console.log(JSON.parse(data)); this.local = JSON.parse(data) this.count() } else { this.local = [] } } })