2

继上一篇搭建了这个Todo App的框架之后,我们轻松实现了为App添加一个task,这次需要实现的是对task的编辑,删除,完成等功能。如果你认真看完,你会发现:在Vue中,一切原来那么简单!

编辑一个task

我们之前通过下面的代码将每个task循环出来:

<li v-repeat="task: tasks"
    class="list-group-item">
    <span>{{ task.body }}</span>
</li>

有了每个task之后,我们准备实现的是在用户双击task时候,就是双击<span>{{ task.body }}</span>的时候,用户可以对该task进行编辑。实现的思路我大概是这样想的:

用户双击 --> 拿到task的body部分 --> 删除展示出来的task --> 将task的body部分赋给newTask  --> 回到添加task的流程 

考虑到这里,我们就遇到了一个问题,怎么删除task跑出来了,不是在编辑task么?好吧,顺便在这个时候将删除task实现了吧,反正正常的App都会有删除功能,所以现在我们来先实现删除task。

删除task

为了更好地看到删除task,我为每个task后面加了一个删除task的小按钮:

<span v-on="dblclick: editTask(task)">{{ task.body }}</span>

<button v-on="click: removeTask(task)">&#10007;</button>

上面<button v-on="click: removeTask(task)">&#10007;</button>这一行就是加了一个x删除小按钮,我们在这里使用Vue的事件监听,当用户点击这个x按钮的时候,我们执行removeTask方法,这个方法接受一个参数,就是task本身。所以在todo.js里面的methods部分加上removeTask:

removeTask: function(task) {
    this.tasks.$remove(task);
}

有没有感觉非常简单,就是两行代码而已!这里的$remove方法是Vue官方提供的一个删除方法,其实就是使用了js的slice。接受到task之后,然后删除,easy enough。

在回到前面的编辑task,我们在实现了删除task之后,这个也变得非常容易了。

完善编辑task

按照前面的思路,我们首先需要为task的body绑定一个方法:

<li v-repeat="task: tasks"
    class="list-group-item">
    <span v-on="dblclick: editTask(task)">{{ task.body }}</span>
</li>

类似的,我们监听用户的双击事件,如果用户双击了该span,我们执行editTask方法。所以,我们来写一下editTask方法:

editTask: function(task) {
    this.newTask = task.body;
    this.removeTask(task);
    this.$$.newTask.focus();
},

依然是将editTask放在todo.js的methods部分,该方法接受一个参数,就是需要编辑的task自身,然后将task的body部分赋给newTask,删除原来的task,最后就是为newTask输入框获取一下焦点。这里的newTask因为和input输入框进行了数据双向绑定,那么这个时候input输入框就会自动填充task的body数据。像这样:

替代文字

完成一个task

对于一个Todo App,用户新增一个task之后,主要的目的是为了完成这个task。这时候我们就需要用到task的另一个属性了:completed。这是在前面一直都没有提及到的,现在终于要派上用场了。完成一个task,其实就是将completed属性的值设为true,所以我们来实现一下:

<span v-on="dblclick: editTask(task)">{{ task.body }}</span>

<button v-on="click: removeTask(task)">&#10007;</button>
<button v-on="click: toggleTaskCompletion(task)">&#10004</button>


像删除一个task一样,我在task后面又加了一个打勾的小按钮<button v-on="click: toggleTaskCompletion(task)">&#10004</button>。用户点击这个按钮的时候,执行toggleTaskCompletion方法,为什么叫toggleTaskCompletion而不叫completeTask呢,因为考虑到用户在点完成之后,有可能反悔了,当他再次点击的时候,task又回到了未完成的状态。所以上代码吧:


toggleTaskCompletion: function(task) { task.completed = ! task.completed; },

这个方法中,我们只是将task中的completed属性设置为它的相反值,用户点击一次,这个值就改变一次。刚写完这个方法,你可能会迫不及待去点击完成按钮,但是这个时候貌似没有什么效果,但是chrome的console又没有报错,这是怎么回事?

其实答案就是:这段代码确实正确的执行了,只是我们在展示task的时候没有根据task的completed状态来筛选认为而已。

所以,为了实现这一功能,我们进而引入Vuejs的filters部分。

实现完成task与未完成的task分离

在实现之前,我们不妨用一个区域来展示完成的task,一个区域来展示未完成的task,所以跟展示task时候很相似:




<div v-show="tasks.length"> <h1>Tasks ({{ tasks.length }})</h1> <ol class="list-group"> <li v-repeat="task: tasks | inProcess" class="list-group-item" > <span v-on="dblclick: editTask(task)">{{ task.body }}</span> <button v-on="click: removeTask(task)">&#10007;</button> <button v-on="click: toggleTaskCompletion(task)">&#10004</button> </li> </ol> </div> <!-- The List of Completed Tasks --> <h2>Completed </h2> <ol class="list-group"> <li v-repeat="task: tasks | filterBy true in completed" class="list-group-item" > {{ task.body }} <button v-on="click: toggleTaskCompletion(task)">&#10007;</button> </li> </ol>

我们在上面用两种方式来实现了Vuejs的filter,一个是filterBy true in completed,这是说只要completed属性为true的task,另一个就是inProcess,这个就需要我们自己来实现一下:


data: { tasks: [], newTask: '' }, filters: { inProcess: function(tasks) { return tasks.filter(function(task){ return ! task.completed; }); } },

上面的代码就是一个简单的filter实现,return ! task.completed;的意思是返回task.completed的值为false的task。

这里我们就简单的实现了完成任务了:

替代文字


JellyBool
16.2k 声望2k 粉丝

给学网 GeiXue.com 创始人:让每一个热爱编程的人都学有所成的精品课程。