删除todo练习参考答案

255 0 2019年1月14日

练习一

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 --

最后更新:2018-11-11 12:21:12

0 条评论 / 0 人参与