Javascript Vue道具在子组件中未正确更新

Javascript Vue道具在子组件中未正确更新,javascript,vue.js,vue-component,vue-reactivity,vue-props,Javascript,Vue.js,Vue Component,Vue Reactivity,Vue Props,我有一个从父组件接收道具的子组件。我添加了一个事件,用于在单击按钮时更新父组件中的道具。但子组件未检测到道具更改 近似代码: 父组件: <template> <table> <Student v-for="(student, index) in students" :key="index" :student="student" :attendance=&quo

我有一个从父组件接收道具的子组件。我添加了一个事件,用于在单击按钮时更新父组件中的道具。但子组件未检测到道具更改

近似代码:

父组件:

<template>
  <table>
    <Student v-for="(student, index) in students"
      :key="index"
      :student="student"
      :attendance="attendance[student.id]"
      @attended-clicked="changeAttendance"
    ></student>
  </table>
</template>

<script>
  export default {
    data() {
      return {
        students: [
          {id: 1, name: 'Pepito'},
          {id: 2, name: 'Sue'},
        ],
        attendance: {
          1: {attended: true},
          2: {attended: false},
        }
      }
    },
    methods: {
      changeAttendance(studentId) {
        this.attendance[studentId].attended = !this.attendance[studentId].attended;
      }
    }
  }
</script>
<template>
  <tr>
    <td>{{ student.name }}</td>
    <td><v-btn :color="attendance.attended ? 'green' : 'red'"
          @click="$emit('attended-clicked', student.id)"
        >Attended</v-btn>
  </tr>
</template>

<script>
  export default {
    props: ['student', 'attendance']
  }
</script>
没有区别


我很感激你能洞察到我做错了什么,谢谢

根据评论,根本问题是
出勤
设置为
{}
,这意味着
出勤[student.id]
对象实际上不在那里,或者不再被跟踪。这是问题中提供的
Vue.set
示例代码应该做的事情

基本上,我看到了两种解决方法:

  • 将Attention设置为在API返回结果时始终使所有学生ID可用,使对象始终具有一个已在工作的对象
  • 当您需要从出席人数中获取值时,开始跟踪反应性
  • 因为我不知道API以及如何调用它,所以我将为选项2提供一个答案。提供的代码几乎正常工作,只需对
    家长组件进行两次更改,即可确保始终填写学生出勤对象,并在将来对其进行跟踪:

    <template>
      <table>
        <!-- :attendance needs an object to work -->
        <Student
          v-for="(student, index) in students"
          :key="index"
          :student="student"
          :attendance="attendance[student.id] || {}"
          @attended-clicked="changeAttendance"
        />
      </table>
    </template>
    
    <script>
    import Vue from "vue";
    import StudentVue from "./Student.vue";
    
    export default {
      data() {
        return {
          students: [{ id: 1, name: "Pepito" }, { id: 2, name: "Sue" }],
          attendance: {}
        };
      },
      methods: {
        changeAttendance(studentId) {
          // make sure to have an object when accessing a student!
          let attendance = this.attendance[studentId] || {};
          attendance.attended = !attendance.attended;
          // start tracking - this will always "reset" the tracking though!
          Vue.set(this.attendance, studentId, attendance);
        }
      },
      components: { Student: StudentVue }
    };
    </script>
    

    如果代码库在其他组件中使用
    this.something[something]
    ,则
    this.getAttention
    可能看起来有点不一致。在这种情况下,最好先将API调用的结果更改为所有学生,并为他们设置默认值,然后再将其提供给
    父组件。就我个人而言,我会尝试使用这个选项。我会使用
    this.$set
    而不是
    Vue.set
    来摆脱
    import Vue
    行…;)

    是否可以生成代码段不确定如何生成包含多个vue组件和vuetify的代码段。虽然
    学生
    出勤
    应该是一个数组,但我会研究它guess@Chris这就是你需要的吗:?这是一个
    <template>
      <table>
        <!-- :attendance needs an object to work -->
        <Student
          v-for="(student, index) in students"
          :key="index"
          :student="student"
          :attendance="attendance[student.id] || {}"
          @attended-clicked="changeAttendance"
        />
      </table>
    </template>
    
    <script>
    import Vue from "vue";
    import StudentVue from "./Student.vue";
    
    export default {
      data() {
        return {
          students: [{ id: 1, name: "Pepito" }, { id: 2, name: "Sue" }],
          attendance: {}
        };
      },
      methods: {
        changeAttendance(studentId) {
          // make sure to have an object when accessing a student!
          let attendance = this.attendance[studentId] || {};
          attendance.attended = !attendance.attended;
          // start tracking - this will always "reset" the tracking though!
          Vue.set(this.attendance, studentId, attendance);
        }
      },
      components: { Student: StudentVue }
    };
    </script>
    
    <template>
      <table>
        <Student
          v-for="(student, index) in students"
          :key="index"
          :student="student"
          :attendance="getAttendance(student.id)"
          @attended-clicked="changeAttendance"
        />
      </table>
    </template>
    
    <script>
    import Vue from "vue";
    import StudentVue from "./Student.vue";
    
    export default {
      data() {
        return {
          students: [{ id: 1, name: "Pepito" }, { id: 2, name: "Sue" }],
          attendance: {}
        };
      },
      methods: {
        changeAttendance(studentId) {
          let attendance = this.getAttendance(studentId);
          attendance.attended = !attendance.attended;
        },
        getAttendance(studentId) {
          const studentAttendance = this.attendance[studentId];
          if (!studentAttendance) {
            Vue.set(this.attendance, studentId, { attended: false });
          }
          return this.attendance[studentId];
        }
      },
      components: { Student: StudentVue }
    };
    </script>