用Vue 对ToDoList 的初步实现
1.输入框的实现:
<input type="text" v-model="value" @keydown.enter="add">
v-model=“value” 用来进行输入数据的双向绑定。
@keydown.enter=“add” 用来添加事件。
而时间的添加需要考虑很多,暂且考虑到的是输入的值为空怎么办,输入的数据存到哪里。
所以data 数据中除了value外还需要一个列表数组(list :[])来存放数据。
这样初步的add事件如下:
add(){
if(this.value.trim() == '') return
this.list.push(value:this.value)
this.value =''
},
2. 列表:
因为正在进行和已完成的列表类似,已完成列表可以在正在进行中列表进行修改,扩展。
2.1 正在进行中:
首先进行页面的布置,所需要的元素有列表,列表中的复选框、文本框、删除按钮。要说的是文本框的作用,在修改时出现文本框进行修改,这里涉及到弹出的时机的问题,后面会提到。
<ul>
<li v-for = "(item,index) in list" :key="index" >
<input type="checkbox" @click.prevent = "changeState(item)">
<span @click= "changeInd(item,index)">{{item}}</span>
<input type="text" @blur = "changeVlu" v-model="changeValue">
<b @click = "del(index)">删除</b>
</li>
</ul>
其中 : li 根据list 列表中的数据进行遍历创建标签。
另:v-for循环数据,当用for来更新已经被渲染的元素时,需要为每项添加key(也就是每项的唯一id),为了使 Vue能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。
复选框的点击事件与本身有冲突所以在点击事件上添加prevent 来避免,达到改变list的完成情况。
输入文本添加span标签和点击事件的要和下面的input输入框进行交互显示,当点击span时span隐藏,input显示。而需要修改的文本也需要一个变量来暂时的储存,所以用changeValue 来双向绑定。然后添加失焦事件来进行修改。同时还需要的时修改元素的下标。changeIndex。
重点 : 如何判断 事情的完成情况?
分析: 当输入完成后状态为”正在进行中“,点击复选框改变状态”已完成“。这就需要一个参数来表明状态。这就需要在添加时就表明状态,所以对添加事件进行修改。
add(){
if(this.value.trim() == '') return
this.list.push({
value:this.value,
done: false
})
this.value =''
}
用done来解决这个问题。
具体事件如下:
//状态
changeState(item){
item.done = !item.done
},
//修改事件
changeInd(item,index){
this.changeIndex = index;
this.changeValue = item.value
},
//修改输入框事件
changeVlu(){
this.list[this.changeIndex].value = this.changeValue;
this.changeIndex=-1;
this.chengeValue ='';
}
//删除事件
del(index){
this.list.splice(index,1)
},
用v-show=“item.done” 来判断li的显示与隐藏。
用changeIndex 的值来判断span和input的显示与隐藏,等于-1时span显示,当等于当前下标时input显示。
2.2 已完成
已完成部分与正在进行中部分大相径庭。需要修改的是当前复选框的选中状态 和li 的显示状态。
3. 存储实现:
存储只需要监听list的变化来用localStorage存储。
localStorage.setItem('todolist',JSON.stringify(arr))
因为list数组中存储着对象,所以监听要进行深度监听 。
而页面加载完成后需要将localStorage的数据读取 ,所以要使用生命周期函数来给list初始化。
4.list 中数据的数量:
使用计算属性,来统计”已完成“和”正在进行中“的数量。用过滤器来进行统计。
this.list.filter(item =>{
return item.done == false;
}
5.具体代码:
//页面部分
<template>
<div>
<input type="text" v-model="value" @keydown.enter="add">
<hr>
<h2>正在进行中({{yesNum}})</h2>
<ul>
<li v-for = "(item,index) in list" :key="index" v-show="!item.done">
<input type="checkbox" @click.prevent = "changeState(item)">
<span @click= "changeInd(item,index)" v-show="changeIndex !==index">{{item.value}}</span>
<input type="text" v-show="index==changeIndex" @blur = "changeVlu" v-model="changeValue">
<b @click = "del(index)">删除</b>
</li>
</ul>
<hr>
<h2>已完成({{noNum}})</h2>
<ul>
<li v-for = "(item,index) in list" :key="index" v-show="item.done">
<input type="checkbox" checked @click.prevent = "changeState(item)">
<span @click= "changeInd(item,index)" v-show="changeIndex==-1">{{item.value}}</span>
<input type="text" v-show="changeIndex==index" @blur = "changeVlu" v-model="changeValue">
<b @click = "del(index)">删除</b>
</li>
</ul>
</div>
</template>
//数据
data(){
return {
value : '',
list : [],
changeIndex:-1,
changeValue : ''
}
}
//计算属性
computed:{
yesNum(){
let arr = this.list.filter(item =>{
return item.done == false;
})
return arr.length;
},
noNum(){
let arr = this.list.filter(item =>{
return item.done == true;
})
return arr.length;
}
}
//生命周期
created(){
let list = localStorage.getItem('todolist')
if(list){
this.list = JSON.parse(list)
}
}
//监听
watch:{
list :{
handler(arr){
localStorage.setItem('todolist',JSON.stringify(arr))
},
deep:true
}
}
//方法
methods: {
add(){
if(this.value.trim() == '') return
this.list.push({
value:this.value,
done: false
})
this.value =''
},
del(index){
this.list.splice(index,1)
},
changeState(item){
item.done = !item.done
},
changeInd(item,index){
this.changeIndex = index;
this.changeValue = item.value
},
changeVlu(){
this.list[this.changeIndex].value = this.changeValue;
this.changeIndex=-1;
this.chengeValue ='';
}
}
hangeInd(item,index){
this.changeIndex = index;
this.changeValue = item.value
},
changeVlu(){
this.list[this.changeIndex].value = this.changeValue;
this.changeIndex=-1;
this.chengeValue ='';
}
}