Vue 道具没有在子组件中正确更新
Posted
技术标签:
【中文标题】Vue 道具没有在子组件中正确更新【英文标题】:Vue prop not updating properly in a child component 【发布时间】:2020-12-11 01:00:05 【问题描述】:我有一个从父组件接收道具的子组件。我添加了一个事件来在单击按钮时更新父组件中的道具。但是子组件并没有检测到prop的变化。
大概代码:
父组件:
<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>
我已尝试使代码尽可能少,以便让您了解我想要实现的目标。期望是当按钮被点击时,attendance.attended
会发生变化。
我可以验证使用 Vue 开发人员工具单击时该值是否正在更改(尽管我必须按下“强制刷新”按钮才能看到更改)。但显然,孩子的观点并没有接受这种变化。
我在这里做错了什么会破坏反应性吗?
我也尝试过使用Vue.set
和一些类似这样的代码:
methods:
changeAttendance(studentId)
let attendance = this.attendance[studentId];
attendance.attended = !attendance.attended;
Vue.set(this.attendance, studentId, attendance);
没有区别。
感谢您对我做错的任何见解,谢谢!
【问题讨论】:
你能做一个sn-p 不知道如何用多个 vue 组件制作 sn-p 和 vuetify。不过我会调查的students
和 attendance
我猜应该是一个数组
@Chris 这是你需要的吗:s8o8q.csb.app?
这是sandbox
【参考方案1】:
根据 cmets,根本问题是 attendance
被设置为 ,这意味着根据 change detection part in the VueJS docs,
attendance[student.id]
对象实际上并不存在或不再被跟踪。这就是问题中提供的Vue.set
示例代码应该做的事情。
基本上我看到了两种解决方法:
-
将出勤设置为在 API 返回结果时始终使所有学生 ID 可用,从而使对象始终具有已经工作的对象
当您需要从
attendance
获取值时开始跟踪反应性。
由于我不知道 API 以及它是如何被调用的,我将为选项 2 提供答案。提供的代码几乎可以工作,它只需要对 Parent
组件进行两次更改,以确保学生考勤对象总是被填满,将来会被跟踪:
<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.attendance[student.id] ||
被多次使用,我将其封装到getAttendance(studentId) ...
函数中。在那里,Vue.set
可用于在对象之前不存在的情况下开始跟踪,从而使changeAttendance
更简单一些,||
的意图更明确。
<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>
如果代码库在其他组件中使用this.something[something]
,this.getAttendance
可能看起来有点不一致。在这种情况下,最好先将 API 调用的结果更改给所有学生,然后再将其提供给Parent
组件。就个人而言,我会尝试使用该选项。我会使用this.$set
而不是Vue.set
来摆脱import Vue
线... ;)
【讨论】:
以上是关于Vue 道具没有在子组件中正确更新的主要内容,如果未能解决你的问题,请参考以下文章