简体   繁体   English

从子组件更新父组件的对象数组的正确方法是什么?

[英]What's the right approach to update a parent's component array of objects from a child component?

I have a complex form with different tabs.我有一个带有不同选项卡的复杂表单。 I use vue-router to switch between these and display different modular components in a router-view for each one of them.我使用vue-router在这些之间切换,并在router-view中为它们中的每一个显示不同的模块化组件。 In these tabs I have child components with sometimes other nested child components.在这些选项卡中,我有子组件,有时还有其他嵌套的子组件。 I use the event bus approach to pass data from these child components up in tree.我使用event bus方法将来自这些子组件的数据向上传递到树中。 I'm doing this because the final tab will be a summary of the form, and I will need access to all the form data.我这样做是因为最后一个选项卡将是表单的摘要,我需要访问所有表单数据。 At the moment I'm using something like the below.目前我正在使用类似下面的东西。

For example using this structure:例如使用这种结构:

|App
--|Start
--|Question 1
  --|Answer 1
  --|Answer 2
--|Question 2
...

In the root component (App):在根组件(App)中:

data() {
  return {
    questions: 0,
    answers: []
  }
},
created() {
    eventBus.$on('answer-added', answer => {
        let answer_exists = false
        this.answers.forEach( (e, i) => {
            if(e.id == answer.answer_id) answer_exists = true
        });
        if(!answer_exists) this.answers.push({
            id: answer.answer_id,
            answer: answer.answer_text
        })
    });
}

What's the proper way to create/update/delete the array of answers in the App component every time an event from the child is fired?每次触发来自孩子的事件时,在 App 组件中创建/更新/删除答案数组的正确方法是什么? I'm sure there must be a much better way than iterating over the array elements to check whether the answer already existed or not... Just can't figure it out.我相信肯定有比遍历数组元素更好的方法来检查答案是否已经存在......只是无法弄清楚。

Do you mean something like:你的意思是这样的:

if (!this.answers.find(a => a.id === answer.answer_id)) {
    this.answers.push(/* ... */);
}

What you are doing is more or less right.你所做的或多或少是对的。 There is no escape from the loop.无法逃脱循环。 However, there are certain things you can improve upon.但是,您可以在某些方面进行改进。 Instead of forEach , you can use Array.some method .代替forEach ,您可以使用Array.some方法 Alternately, you can use Array.find method:或者,您可以使用Array.find方法:

eventBus.$on('answer-added', answer => {

    // Instead of using forEach, you can use Array.some() method
    const answerExists = this.answers.some((x) => e.id == answer.answer_id);

    if (!answerExists) {
      this.answers.push({
        id: answer.answer_id,
        answer: answer.answer_text
      });
    }
});

Second, there is no problem with using an event bus , but it is generally used for a sibling or cross-component communication.其次,使用事件总线是没有问题的,但它一般用于兄弟或跨组件通信。 When all the components are in the same ancestor or parent hierarchy, using $emit for events is the right way.当所有组件都在同一个祖先或父层次结构中时,使用$emit事件是正确的方法。

In your case, even though you have a nested components hierarchy, as the application evolves, a hierarchy can get really deep and you will quickly lose the track of typical publish-subscribe mechanism of the event bus.在你的情况下,即使你有一个嵌套的组件层次结构,随着应用程序的发展,层次结构会变得非常深,你很快就会忘记事件总线的典型发布-订阅机制。 Even if it means re-emitting the same events from intermediate components, you should follow this practice.即使这意味着从中间组件重新发出相同的事件,您也应该遵循这种做法。

For anyone who comes across with the same issue, the problem I encountered is resolved by using a Simple Global Store .对于遇到相同问题的任何人,我遇到的问题都可以通过使用Simple Global Store来解决。 Other more complex scenarios would possibly require Vuex as suggested by @Dan above.正如上面@Dan 所建议的那样,其他更复杂的场景可能需要Vuex

Pass a callback from parent to child.将回调从父级传递给子级。 Now they can communicate bottom up.现在他们可以自下而上地进行交流。 The child can pass any data the parent might want and then the parent can take back control and use its state or closure state.孩子可以传递父母可能想要的任何数据,然后父母可以收回控制权并使用其状态或关闭状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM