如何在VueJS中$ watch列表项的属性

时间:2018-09-18 16:08:26

标签: vue.js

如何$ watch监视列表项的特定属性?例如,在下面的代码中,我想知道任何TODO列表项的Done属性何时更改。

我从文档中看到可以监视对象的子属性,例如下面的代码中的myObjects.done,但是我不确定列表的语法。

我还应该提到,我宁愿$ watch数据,也不愿在UI中放置事件处理程序,并在任何会更改属性的位置调用函数

var vm = new Vue({
  el: "#app",
  data: {
    myObject: { done: true },
    todos: [
      { text: "Learn JavaScript", done: false },
      { text: "Learn Vue", done: false },
      { text: "Play around in JSFiddle", done: true },
      { text: "Build something awesome", done: true }
    ]
  },
});

//This works wonderfully on non list items
vm.$watch("myObject.done", function(val)
{
    console.log("myObject.done changed", val);
});

//How do I monitor changes to the done property of any of the todo items?
vm.$watch("todos[*].done", function(val)
{
    console.log("todos.done changed", val);
})

JSFiddle在这里:http://jsfiddle.net/eywraw8t/376544/

3 个答案:

答案 0 :(得分:3)

使用当前方法,您必须深入观察数组并进行一些繁重的计算才能找出更改后的元素。检查此链接的示例: Vue - Deep watching an array of objects and calculating the change?

我认为更好的方法是使用change事件处理程序:

<input type="checkbox" v-model="todo.done" @change="onTodoChange(todo, $event)">

JSFiddle:http://jsfiddle.net/47s0obuc/

答案 1 :(得分:1)

要监视特定属性,我将为列表项创建另一个组件,并将该项作为值传递,以监视该组件的更改。

Vue.component("TaskItem", {
    template: `
        <li
            class="task-item"
            :class="{ done: complete }"
        >
            <p>{{ task.description }}</p>
            <input type="checkbox" v-model="complete">
        </li>
    `,
    props: ["task"],
    computed: {
        complete: {
            set(done) {
                this.$emit("complete", this.task, done);
                // we force update to keep checkbox state synced
                // in case if task.done was not toggled by parent component
                this.$forceUpdate();
            },
            get() {
                return this.task.done;
            }
        }
    }
});

new Vue({
    el: "#app",
    template: `
        <div>
            <ul class="task-list">
                <TaskItem
                    v-for="(task, i) in tasks"
                    :key="i"
                    :task="task"
                    @complete="complete"
                />
            </ul>
            <button @click="completeFirstTask">Complete first task</button>
        </div>
    `,
    data() {
        return {
            tasks: [
                { description: "Get milk", done: false },
                { description: "Barber shop", done: true },
                { description: "Fix sleep cycle", done: false }
            ]
        };
    },
    methods: {
        complete(item, done) {
            item.done = done;
        },
        completeFirstTask() {
            this.tasks[0].done = true;
        }
    }
});

https://codesandbox.io/s/wqrp13vp25

答案 2 :(得分:0)

我用了这个,对我有用。

var vm = new Vue({
  el: "#app",
  data: {
    myObject: { done: true },
    todos: [
      { text: "Learn JavaScript", done: false },
      { text: "Learn Vue", done: false },
      { text: "Play around in JSFiddle", done: true },
      { text: "Build something awesome", done: true }
    ]
  },
  watch:{
  todo: function(val) {
  console.log ("This TODO is Done", val)
  }
});
<template>
  <div class="mainDiv" v-for="(index, todo) from todos">
    <div>{{todo.text}}</div>
    <input type="checkbox" v-model="todo[index].done">
  </div>
</template>