为什么实际触发此事件?

时间:2019-10-22 07:35:31

标签: vue.js

我在使用路由的vue项目中,其教学课程:https://www.youtube.com/watch?v=Wy9q22isx3U 完整代码的仓库在这里: https://github.com/bradtraversy/vue_crash_todolist

我的Home.vue看起来像这样:

<template>
  <div id="app">
  <AddTodo v-on:add-todo="addTodo"/>
    <Todos v-bind:todos="todos" v-on:del-todo="deleteTodo"/>
  </div>
</template>

<script>
import AddTodo from '../components/AddTodo'
import Todos from '../components/Todos'

export default {
  name: 'home',
  components: {
    Todos,
    AddTodo
  },
  data() {
    return {
      todos: [
        {
          id: 1,
          title: "Todo one",
          completed: false
        },
        {
          id: 2,
          title: "Todo two",
          completed: true
        },
        {
          id: 3,
          title: "Todo three",
          completed: false
        }
      ]
    }
  },
  methods: {
    deleteTodo(id){
      this.todos = this.todos.filter(todo => todo.id != id)
    },
    addTodo(newTodo){
      this.todos = [...this.todos, newTodo]
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

这里重要的是标记中的Todos元素。 它是导入TodoItem本身的复杂组件。 现在Todos看起来像这样:

<template>
  <div>
    <div v-bind:key="todo.id" v-for="todo in todos">
      <TodoItem v-bind:todo="todo" v-on:del-todo="$emit('del-todo', todo.id)"/>
    </div>
  </div>
</template>

<script>
import TodoItem from './TodoItem.vue'


export default {
  name: "Todos",
  components: {
    TodoItem
  },
  props: ["todos"]

}

</script>

<style scoped>

</style>

它导入了TodoItem,在这里:

<template>
  <div class="todo-item" v-bind:class="{'is-complete':todo.completed}">
    <p>
      <input type="checkbox" v-on:change="markComplete">
      {{todo.title}}
      <button @click="$emit('del-todo', todo.id)"class="del">x</button>
    </p>
  </div>
</template>

<script>
export default {
  name: "TodoItem",
  props:["todo"],
  methods: {
    markComplete(){
      this.todo.completed = !this.todo.completed
    }
  }
}

</script>

<style scoped>
  .todo-item {
    background: #f4f4f4;
    padding: 10px;
    border-bottom: 1px #ccc dotted;
  }
  .is-complete {
    text-decoration: line-through;
  }
  .del {
    background: #ff0000;
    color: #fff;
    border: none;
    padding: 5px 9px;
    border-radius: 50%;
    cursor: pointer;
    float: right;
  }
</style>

现在让我困惑的是围绕发射事件的语法。 在TodoItem中,我从按钮发出了这个事件:

<button @click="$emit('del-todo', todo.id)"class="del">x</button>

现在这对我来说是完全可以理解的,因为我们已使用“ @click”指定了事件触发器。 然后将其导出到父级Todos.vue,在那里我们可以看到:

<TodoItem v-bind:todo="todo" v-on:del-todo="$emit('del-todo', todo.id)"/>

我在这里开始感到困惑。 同样,在长语法中,定义了事件触发器:

v-on:del-todo

但是del-todo并不是事件触发器。它既不单击,也不更改,也不输入。 那么,这些代码如何工作?当vue.js遇到上述代码时,意味着什么?

然后我对Home.vue的困惑更加严重

<Todos v-bind:todos="todos" v-on:del-todo="deleteTodo"/>

第三次指定事件触发器。 并且第二次,此事件触发器未指定“本地”触发器,如click。

现在我已经把头缠住了,至少可以克服一些感觉。 在Todos.vue和Home.vue中,del-todo触发后,指定的事件似乎会执行。因此,它们就像回调一样,采用del-todo的返回值。 在Todos.vue中,触发del-todo会向其父级Home.vue发出del-todo。 那是对的吗?

Home.vue然后在触发del-todo时触发deleteTodo。 但是,deleteTodo要求通过该参数传递ID,但是有趣的是,<Todos v-bind:todos="todos" v-on:del-todo="deleteTodo"/>不需要。 尽管如此,该功能仍然有效。那么id如何到达deleteTodo?

TodoItem.vue中出现类似的问题。在这里,调用了del-todo,但是实际上我们在TodoItem.vue中的脚本中的任何地方都没有对该函数的任何形式的声明。再说一遍,当遇到一个没有被定义的函数被发出/调用的情况时,vueJS意味着什么?

2 个答案:

答案 0 :(得分:1)

正在发生的事情是,每次单击时,都会向父组件发送一个事件AND值,父组件具有一个侦听器v-on:del-todo,这意味着一旦侦听del-todo事件触发/处理后,它将再次向上发射它,直到到达您要实际操作数据的组件为止(根据ID删除项目)。
注意:该值会隐式传递到处理程序函数deleteTodo中,因此即使它不在显式位置(即deleteTodo($event)也存在)。

答案 1 :(得分:1)

在Vue.js中,不仅有事件click changeinput,还允许您定义自定义事件。您所要做的全部操作是使用$emit('my-custom-event', param1, param2)在子组件中引发一个事件,并使用v-on:my-custom-event="handler"将其捕获到直接父组件中(您也可以写@my-custom-event,这就是同义词)。处理程序是一个函数,它在发出事件时采用传递的参数。 Todos组件中的处理程序将捕获事件del-todo,并引发一个具有相同名称的新事件。 Home组件捕获到该事件,并将其函数deleteTodo定义为其处理程序,因此将调用此函数(随事件传递的id是deleteTodo的参数)