添加todo

2019-01-0710287 阅读2 评论

在教程的第一篇 入门仪式:Hello Vue 中我们演示了一个 Vue 绑定 input 输入值的示例,添加 todo 的功能和那个例子有异曲同工之妙。

为了知道用户输入了什么内容,我们使用 v-model 指令将 input 的 value 值和 Vue 的实例绑定,这样在 Vue 中我们就知道了用户输入的值。然后我们监听用户按下回车的事件,一旦这个事件被触发,我们就在 Vue 实例中调用相应的方法,把新的值添加到 todos 列表中,下面来一步步完成上面的步骤。

绑定 input 的输入:

<div id="todo-app">
    ...
  <div>
    ...
    <input type="text" 
           placeholder="添加 todo" 
           v-model="newTodoTitle"/>
  </div>
    ...
</div>
...
<script>
    var app = new Vue({
        el: '#todo-app',
        data: function () {
            return {
                todos: [],
                newTodoTitle: ''
            }
        },
    })
</script>

我们把预先填充在 todos 列表的值清空了,因为一开始是没有 todo 的。然后我们使用 v-model 指令将 input 的 value 属性的值与 Vue 实例的 newTodoTitle 值绑定。注意这里绑定的数据可以取任何名字,不一定要和 input 的属性 value 相同。

然后我们监听键盘敲击回车的事件:

<div id="todo-app">
    ...
   <input type="text" 
          placeholder="添加 todo"
          v-model="newTodoTitle"
          @keyup.enter="addTodo"/>
    ...
</div>
...
<script>
    var app = new Vue({
        el: '#todo-app',
        data: function () {
            return {
                todos: [],
                newTodoTitle: ''
            }
        },
    })
</script>

注意到 @keyup.enter="addTodo",我们之前的示例中绑定过 click 事件,绑定键盘按键的事件为 keyup,然后我们使用 enter 对事件进行修饰,表明这个事件是按下回车,而不是按下别的什么键。Vue为按键提供了很多修饰符,可以参考 Vue 按键修饰符的官方文档。事件绑定后,一旦用户按下回车,就会调用后边的 addTodo 方法。

实现 addTodo 方法:

<script>
    let id = 0; // 用于 id 生成
    var app = new Vue({
        ...
        methods: {
            addTodo: function () {
                this.todos.push({id: id++, title: this.newTodoTitle});
                this.newTodoTitle = ''
            }
        }
    })
</script>

示例中已经说过方法声明在 Vue 对象的 methods 属性里。这个 addTodo 方法做的事情很简单,生成一个新的 todo 对象,然后将其添加到 todos 列表里(push 方法就是把一个元素加入到数组的末尾),然后将用户的输入值清空。始终注意这里 newTodoTitle 和输入框的 value 值是双向绑定的,任何一个值改变,相应的值都会跟着变。

打开浏览器,试着添加几个 todo 吧!

练习

练习一:我们的方法有一个小 bug,如果用户什么内容也没有输入,但是敲下了回车,我们的应用会为其创建一个空的 todo,正确的效果应该是不做任何动作。尝试修改程序,实现正确的效果。

练习二:能否进一步地,当用户尝试创建空的 todo 时,我们的输入框边框变红色,提醒用户没有任何内容输入,以及在输入框后边显示“请输入内容”之类的提示信息呢?(hint:结合之前示例中给出的计算属性、动态绑定 class、v-if 指令来实现,你可能需要参考 Vue 的官方文档了解这些内容)。

涉及的官方文档:

-- EOF --

2 评论
登录后回复
richmanwu
2021-04-27 16:00:14
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vue Todo</title>
  <style>
    .completed {
      text-decoration: line-through;
    }

    .selected {
      color: red;
    }
  </style>
</head>
<body>
<div id="todo-app">
  <div>
    <input type="button" value="全部标为完成"/>
    <input type="text" placeholder="添加 todo" v-model='newTodoTitle' @keyup.enter='addTodo' v-bind:style="styleObject" /><span v-if='seen'>你没有输入任何内容,无法添加</span>
  </div>
  <!-- todo list -->
  <ul>
    <li v-for='todo in todos' :key='todo.id'>
      <span>{{todo.title}}</span>
      <input type="button" value="标为完成">
      <input type="button" value="删除">
      <input type="text" value="编辑 todo...">
    </li>
  </ul>
  <!-- end todo list -->
  <div>
    <span>剩余 3 项未完成 ---</span>
    <span>筛选:
      <input type="button" class="selected" value="全部">
      <input type="button" value="进行中">
      <input type="button" value="已完成">
      <input type="button" value="清除已完成">
      <input type="button" value="清除全部">
    </span>
  </div>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
<script>
  let id = 1;
    var app = new Vue({
        el: '#todo-app',
        data: function () {
          return {
            todos: [],
            newTodoTitle: '',
            seen: false,
            styleObject: {
              borderColor: 'black',
            },
          }
        },
        methods: {
          addTodo: function(){
            if(!this.newTodoTitle){
              this.styleObject.borderColor = 'red'
              this.seen = true
              return false
            }
            this.todos.push({id:id++, title: this.newTodoTitle});
            this.newTodoTitle = ''
            this.seen = false
            this.styleObject.borderColor = 'black'
          }
        },
    })
</script>
</body>
</html>
回复
wheatPassersby richmanwu
2021-08-10 03:46:36

这个实现有颜色问题吧?试了一下,没有颜色体现呢...

回复

目录