从子组件Vue更新父模型

时间:2017-01-15 15:47:52

标签: vue.js

我有一个非常小的应用程序,有一个捐款表格。表单引导用户完成填写信息的步骤。我有一个主要组件,它是表单包装器和主Vue实例,它包含所有表单数据(模型)。所有子组件都是捐赠过程中的步骤。每个子组件都有要填写的输入字段,这些字段将更新父模型,以便在提交表单时我拥有父模型中的所有表单数据。以下是组件的组合方式:

<donation-form></donation-form> // Main/Parent component

donation-form组件内:

<template>
    <form action="/" id="give">
        <div id="inner-form-wrapper" :class="sliderClass">
            <step1></step1>
            <step2></step2>
            <step3></step3>
        </div>
        <nav-buttons></nav-buttons>
    </form>
</template>

现在,我正在设置每个子组件中输入的数据,然后我有一个watch方法正在监视要更新的字段,然后我将它们推送到$root这样做......

watch: {
    amount() {
        this.$root.donation.amount = this.amount;
    }
}

问题是我的一个步骤我有很多字段,而且我似乎在编写一些重复的代码。此外,我确信这不是最好的方法。

我尝试将数据作为prop传递给我的子组件,但似乎我无法更改子组件中的道具。

更新根实例甚至父实例除了将监视添加到子组件中的每个值之外,还有什么更好的方法?

更多示例 这是我的step2.vue文件 - step2 vue file 这是我的donation-form.vue文件 - donation-form vue file

3 个答案:

答案 0 :(得分:22)

您可以使用enter image description here发回数据。

要使用自定义事件,您的数据应位于父组件中,并作为道具传递给子项:

<step1 :someValue="value" @update="onStep1Update" />

现在您想要从子级接收更新的数据,因此请向其添加一个事件:

this.$emit('update', newData)

您的子组件将发出事件并将数据作为参数传递:

methods: {
  onStep1Update (newData) {
    this.value = newData
  }
}

父组件:

<input />

以下是自定义事件的简单示例:
{{3}}

如果所有step1,step2和step3都包含大量字段和数据,则可以将这些数据封装在子组件中(如果父组件不关心这些行数据)。

因此每个孩子都有自己的数据并与<input v-model="data1" /> <input v-model="data2" />

绑定
const result = this.data1 * 10 + this.data2 * 5
this.$emit('update', result)

但同样,您将通过事件发回结果数据。

int i = 0, counter = 0;
while ((*t) != '\0')
{
    counter++;
    t++;
}

(同样,如果您的应用程序变得越来越复杂,vuex将成为解决方案。

答案 1 :(得分:5)

我个人更喜欢在使用表单时使用通用函数来更新父表,而不是为每个孩子编写一个方法。为了说明 - 有点浓缩 - 在父母中这样:

<template lang="pug">
  child-component(:field="form.name" fieldname="name" @update="sync")
</template>
<script>
export default {
  methods: {
    sync: function(args) { 
      this.form[args.field] = args.value
    }
  }
}
</script>

在子组件中:

<template lang="pug">
  input(@input="refresh($event.target.value)")
</template>
<script>
export default {
  props: ['field', 'fieldname'],
  methods: {
    refresh: function(value) {
      this.$emit('update', {'value': value, 'field': this.fieldname});
    }
  }
}
</script>

答案 2 :(得分:1)

对于您的情况,您可以使用如下的v-model:

<form action="/" id="give">
    <div id="inner-form-wrapper" :class="sliderClass">
        <step1 v-model="step1Var"></step1>
        <step2 v-model="step2Var"></step2>
        <step3 v-model="step3Var"></step3>
    </div>
    <nav-buttons></nav-buttons>
</form>

v-model本质上是用于更新用户输入事件数据的语法糖。

<input v-model="something">

只是语法糖:

<input v-bind:value="something" v-on:input="something = $event.target.value">

您可以在子组件中传递道具:value,并在更改输入字段调用后,将更改step1Var变量。

this.$emit('input', opt)

你可以看看这个answer,在那里你可以看到这个组件的实现,其中变量通过th-v-model传递。