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

时间:2019-06-03 13:47:58

标签: javascript vue.js vuejs2 vue-component

我有一个带有不同标签的复杂表格。我使用vue-router在这些之间进行切换,并在router-view中为其中每个显示不同的模块化组件。在这些选项卡中,我具有子组件,有时还有其他嵌套的子组件。我使用event bus方法将这些子组件中的数据传递到树中。我这样做是因为最后一个选项卡将是表单的摘要,并且我需要访问所有表单数据。目前,我正在使用类似以下的内容。

例如使用以下结构:

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

在根组件(应用程序)中:

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
        })
    });
}

每次触发孩子事件时,在App组件中创建/更新/删除答案数组的正确方法是什么? 我敢肯定,有比遍历数组元素检查答案是否已经存在的更好的方法了……只是想不通。

4 个答案:

答案 0 :(得分:0)

您的意思是:

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

答案 1 :(得分:0)

您所做的或多或少是正确的。从循环中无法逃脱。但是,有些事情可以改进。可以使用Array.some method代替forEach。另外,您可以使用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
      });
    }
});
  

第二,使用事件总线没问题,但是通常用于同级或跨组件通信。当所有组件都位于同一祖先或父层次结构中时,对事件使用$emit是正确的方法。

在您的情况下,即使您具有嵌套的组件层次结构,随着应用程序的发展,层次结构可能会变得很深,您将很快失去对事件的典型发布-订阅机制的了解总线。即使这意味着从中间组件重新发出相同的事件,您也应遵循此做法。

答案 2 :(得分:0)

对于遇到相同问题的任何人,我遇到的问题都可以通过使用Simple Global Store来解决。如上面@Dan所建议的,其他更复杂的情况可能需要Vuex

答案 3 :(得分:0)

将回调从父级传递到子级。现在他们可以自下而上地交流。子级可以传递父级可能想要的任何数据,然后父级可以收回控制权并使用其状态或关闭状态。