练习一
javascript 有一个 confirm 方法,调用该方法浏览器会弹出一个确认框,用户点击确认该方法会返回 true,点取消则不返回 true,因此用该方法可以实现我们的功能,只需修改 removeTodo 方法即可。
removeTodo: function (todo) {
if (!confirm('确认删除?')) {
return
}
this.todos.splice(this.todos.indexOf(todo), 1)
}
即如果用户没有点击确认,则 if 语句会执行,函数直接返回,不做删除操作。
练习二
这个功能的基本思路是,当用户删除某个 todo 后,我们用一个变量将这个删除的 todo 暂时保存下来,如果用户点击了撤销按钮,就把这个暂存的 todo 再插回原来的 todo 列表。为此,我们先给 vue 增加一个 removedTodo 变量,其初始值为 null:
data: function () {
return {
todos: [],
newTodoTitle: '',
removedTodo: null
}
},
如果用户点击了删除 todo 按钮,就把这个删除的 todo 保存到 removedTodo 变量,修改一下 removeTodo 方法:
removeTodo: function (todo) {
let pos = this.todos.indexOf(todo);
this.removedTodo = {
pos: pos,
todo: this.todos.splice(pos, 1)[0]
};
},
注意这里我们先获取了被删除的 todo 在 todo 列表的位置 pos,这个 pos 的作用是记录被删除 todo 的位置,撤销时我们就可以根据这个位置将被删除的 todo 插回原始位置。removedTodo 记录了位置信息和被删除的整个 todo。注意 this.todos.splice(pos, 1) 返回被删除的元素,即使只有一个元素,返回的也是数组,因此我们取索引 0 位置的元素。
让后我们给页面添加一个撤销按钮,该按钮监听点击事件并调用 restoreTodo 方法撤销删除操作:
methods: {
...
restoreTodo: function () {
let pos = this.removedTodo.pos;
let restored = this.removedTodo.todo;
this.todos.splice(pos, 0, restored);
this.removedTodo = null;
}
},
代码很好理解,注意这里 splice 方法第二个参数为 0 表示在数组的指定位置(pos)插入元素。撤销后别忘了将 removedTodo 重新置为 null。
然后加一个按钮,绑定 restoreTodo 的 click 事件:
<!-- todo list -->
<div v-if="hasRemovedTodo">
<br>
<input type="button" value="撤销" @click="restoreTodo()"/>
</div>
...
<!-- end todo list -->
要注意这里我们用 v-if 指令来条件渲染撤销按钮,因为只有当存在被删除的 todo 时,按钮才需要被渲染,如何判断是否存在被删除的 todo 呢,可以根据 removedTodo 是否为 null 来判断,是则没有,否则就有,为此我们创建一个计算属性 hasRemovedTodo 来指示是否存在被删除的 todo:
computed: {
hasRemovedTodo: function () {
return !!this.removedTodo
}
}
撤销拓展
上面我们实现的撤销功能只记录了最近被删除的 todo,如果你连续删除多个 todo,只有最近被删除的 todo 能还原。为了支持多个 todo 还原,我们可以把 removedTodo 这个变量设置为一个栈,每删除一个 todo 就将被删除的 todo 压入栈中,点击撤销则弹出栈顶的 todo 还原,从而实现多步撤销功能。该功能不再实现,留给你作为拓展练习。
练习三
参见后面
-- EOF --