【问题标题】:Vue Component Communication (Parent > Children)Vue组件通信(父>子)
【发布时间】:2019-06-19 11:21:00
【问题描述】:

我有一个父组件(todo-list),里面有一个子组件(todo-item)。我正在尝试在父级中创建一个复选框(检查所有待办事项),以便一键检查所有待办事项。

在父组件中使用 checkAll(),它改变了子组件的 props,但它不改变子组件的数据。

这是父组件 todo-list

<template>
  <div class="todo-list-container">
    <todo-input @addTodo="addTodo"></todo-input>
    <todo-item v-for="(todo, index) in todos" 
      :key="todo.id" 
      :todo="todo" 
      :index="index" 
      :completed="todo.completed"
      @removeTodo="removeTodo"
      @changedCompleted="changedCompleted"
    ></todo-item>
    <div class="flex-container">
      <div class="button-aux-div"></div>
      <a href="#" class="todo-button">
        <input type="checkbox" :checked="!anyRemaining" @change="checkAll">
      </a>
    </div>
  </div>
</template>

<script>

import Vue from 'vue'
import TodoItem from './TodoItem'
import TodoInput from './TodoInput'

export default {
  name: 'todo-list',

  components: {
    TodoItem,
    TodoInput,
  },

  data () {
    return {
      idForTodo: 3,
      todos: [
        {
          'id': '1',
          'title': 'title1',
          'body': 'body1',
          'completed': false,
        },
        {
          'id': '2',
          'title': 'title2',
          'body': 'body2',
          'completed': false,
        },
      ],
      allChecked: false,
    }
  },

  computed: {
    remaining() {
      return this.todos.filter(todo => !todo.completed).length
    },
    anyRemaining() {
      return this.remaining != 0
    }
  },

  methods: {
    addTodo(todoMessage) {
      this.todos.push({
        id: this.idForTodo,
        title: 'title' + this.idForTodo,
        body: todoMessage,
        completed: false,
      })

      this.idForTodo++;
    },

    removeTodo(data) {
      this.todos.splice(data.index, 1);
      this.idForTodo--;
    },

    changedCompleted(data) {
      this.todos.splice(data.index, 1, data.todo)
    },

    checkAll() {
      this.todos.forEach((todo) => todo.completed = event.target.checked)
    },
  },

}
</script>

这是子组件 todo-item

<template>
  <div class="todo-item-container">
    <div class="todo-title-container">
      <div class="todo-id-container">
        <div id="todo-id">
          <h2>{{ id }}</h2>
        </div>
      </div>
      <div id="todo-title"><h2>{{ title }}</h2></div>
      <div class="todo-completed-container">
        <a href="#" class="todo-button">
          <input type="checkbox" v-model="completed" @change="changedCompleted">
        </a>
      </div>
      <div class="todo-delete-container">
        <a href="#" class="todo-button" @click="deletedTodo">×</a>
      </div>
    </div>

    <hr>

    <div class="todo-body-container">
      <p id="todo-body">{{ body }}</p>
    </div>
  </div>
</template>

<script>
export default {
  name: 'TodoItem',

  props: {
    todo : {
      type: Object,
      required: true,
    },
    index : {
      type: Number,
      required: true,
    },
  },

  data () {
    return {
      'id': this.todo.id,
      'title': this.todo.title,
      'body': this.todo.body,
      'completed': this.todo.completed,
    }
  },  

  methods: {

    deletedTodo() {
      this.$emit('removeTodo', {
        'index': this.index,
        'todo': {
          'id': this.id,
          'title': this.title,
          'body': this.body,
          'completed': this.completed,
        }
      })
    },

    changedCompleted() {
      this.$emit('changedCompleted', {
        'index': this.index,
        'todo': {
          'id': this.id,
          'title': this.title,
          'body': this.body,
          'completed': this.completed,
        }
      })
    },
  },
}

</script>

【问题讨论】:

  • 我没有看到 - completed 道具被 child-component 接收
  • @subhasis 下面建议添加一个计算属性。但是我需要将完成的道具从父母传给孩子吗?因为它已经包含在待办事项中。
  • props 是响应式的,您不需要将其放入computed。它可能在这里不起作用,因为 object 是参考值,并且您正在传递对象的地址,因此内部的任何更新都需要得到深入关注。现在 - 如果您将 completed 属性传递给 child 并且每当 completed 获取更新后的child 将获得更新后的值。
  • 当我将完成的道具传递给子组件时,是的,它会更新道具以及子组件中“完成”的数据。但是,当我尝试 checkall 时,父组件中的道具发生了变化,但它并没有改变子组件中“完成”的数据。

标签: vue.js


【解决方案1】:

而不是 'completed': this.todo.completed, 。 使用

computed: {
  completed () {
    return this.todo.completed
  }
}

【讨论】:

  • 这是否意味着组件中的数据不是响应式的,我需要始终将我的 prop 放在计算下?
  • 不,数据是组件是反应性的。但是,如果您从 prop 实例化数据字段,它将不会是响应式的,即更新 prop 不会响应式更新数据字段。
  • 试过了,但收到错误消息:“计算属性“已完成”已分配给但它没有设置器。”这是因为我的复选框上有一个 v-model 到计算属性?
  • 您收到该错误是因为 - 您收到了一个 prop 名称 - completed 并且还创建了具有相同名称的 computed 属性
猜你喜欢
  • 2018-05-08
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 2019-05-10
  • 2016-11-05
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多