对于下面的代码,我的子组件警报在父组件挂载函数中的任何代码之前触发。
结果,在数据准备好之前,子进程似乎已经完成了初始化,因此在重新加载数据之前不会显示数据。
数据本身很好地从API返回,因为原始JSON显示在布局中的v-card
中。
我的问题是如何确保父组件中请求的数据在子组件加载之前准备好?我发现的任何东西都集中在使用props传递的静态数据上,但是当必须首先获取数据时,似乎这完全失败了。
在Parent的mounted()
中,我有这个代码,它是检索数据的。
const promisesArray = [this.loadPrivate(),this.loadPublic()]
await Promise.all(promisesArray).then(() => {
console.log('DATA ...') // fires after the log in Notes component
this.checkAttendanceForPreviousTwoWeeks().then(()=>{
this.getCurrentParticipants().then((results) => {
this.currentP = results
this.notesArr = this.notes // see getter below
})
在父
中检索数据的getterget notes() {
const newNotes = eventsModule.getNotes
return newNotes
}
父模板中的组件:
<v-card light elevation="">
{{ notes }} // Raw JSON displays correctly here
// Passing the dynamic data to the component via prop
<Notes v-if="notes.length" :notesArr="notes"/>
</v-card>
子组件:
...
// Pickingn up prop passed to child
@Prop({ type: Array, required: true })
notesArr!: object[]
constructor()
{
super();
alert(`Notes : ${this.notesArr}`) // nothing here
this.getNotes(this.notesArr)
}
async getNotes(eventNotes){
// THIS ALERT FIRES BEFORE PROMISES IN PARENT ARE COMPLETED
alert(`Notes.getNotes CALL.. ${eventNotes}`) // eventNotes = undefined
this.eventChanges = await eventNotes.map(note => {
return {
eventInfo: {
name: note.name,
group: note.groupNo || null,
date: note.displayDate,
},
note: note.noteToPresenter
}
})
}
...
我对Vue比较陌生,所以如果我忽略了一些基本的东西,请原谅我。我一直在试图解决它的几天,现在不能弄清楚,所以任何帮助是非常感激!
如果您是Vue的新手,我建议您阅读它的完整文档和您正在使用的工具- Vue -class-component(这是Vue插件添加的API,用于将Vue组件声明为类)
- 类组件的注意事项-始终使用生命周期钩子而不是
constructor
所以你应该把代码移到created()
生命周期钩子
constructor()
在这种情况下,这应该足以修复你的代码,但仅仅是因为Notes
组件的使用是由父组件中的v-if="notes.length"
保护的-该组件只有在notes
不是空的情况下才会被创建
在很多情况下这是不够的!
created()
生命周期钩子(和data()
函数/钩子)对每个组件只执行一次。里面的代码是一次性初始化. 因此,当/如果父组件更改notesArr
prop的内容时(有时在将来),eventChanges
将不会得到更新。即使您知道父组件永远不会更新道具,请注意,出于性能原因,当使用v-for
呈现列表或使用v-if
/v-else
在相同类型的组件之间切换时,Vue倾向于在可能的情况下重用现有组件实例-而不是销毁现有组件并创建新组件,Vue只是更新道具。应用程序突然无缘无故地看起来坏了…
这是许多没有经验的用户会犯的错误。你可以在SO上找到很多问题,比如"我的组件没有反应性"。或者"如何强制组件重新渲染";许多答案建议使用:key
黑客或使用观察者....这有时有效,但几乎总是比正确的解决方案复杂得多
正确的解决方案是把你的组件写成纯组件(如果可以的话——有时是不可能的)(这篇文章是针对React的,但原则仍然适用)。在Vue中实现这一点的一个非常重要的工具是计算属性
所以,不是引入eventChanges
的数据属性(它可能是响应的,也可能不是响应的——这在你的代码中不是很清楚),你应该让它成为直接使用notesArr
prop的计算属性:
get eventChanges() {
return this.notesArr.map(note => {
return {
eventInfo: {
name: note.name,
group: note.groupNo || null,
date: note.displayDate,
},
note: note.noteToPresenter
}
})
}
现在只要notesArr
道具被父道具改变,eventChanges
就会被更新,组件将重新渲染
指出:
- 您过度使用
async
。您的getNotes
函数不执行任何异步代码,所以只需删除它。 - 也不要把
async
和then
混在一起——这会混淆
:
const promisesArray = [this.loadPrivate(),this.loadPublic()]
await Promise.all(promisesArray)
await this.checkAttendanceForPreviousTwoWeeks()
const results = await this.getCurrentParticipants()
this.currentP = results
this.notesArr = this.notes
或:
const promisesArray = [this.loadPrivate(),this.loadPublic()]
Promise.all(promisesArray)
.then(() => this.checkAttendanceForPreviousTwoWeeks())
.then(() => this.getCurrentParticipants())
.then((results) => {
this.currentP = results
this.notesArr = this.notes
})
优秀的学习资源