【问题标题】:Avoid mutating props in nested forms避免在嵌套形式中改变 props
【发布时间】:2021-03-24 23:58:46
【问题描述】:

假设我有一个分为两个部分的表单,每个部分通过道具与父表单进行通信。如何避免改变从父表单传递的道具?


父窗体.vue

<template>
  <div>
    <AddressForm :form-data="formData.address" />
    <OtherForm :form-data="formData.other" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      formData: {
        address: {
          address_no: "",
          country: "",
        },
        other: {
          remarks: "",
        },
      },
    };
  },
};
</script>

AddressForm.vue

<template>
  <div>
    <input v-model="formData.address_no" />
    <input v-model="formData.country" />
  </div>
</template>

<script>
export default {
  name: "AddressForm",
  props: { formData: { type: Object, required: true } },
};
</script>

OtherForm.vue

<template>
  <div>
    <textarea v-model="formData.remarks" />
  </div>
</template>

<script>
export default {
  name: "OtherForm",
  props: { formData: { type: Object, required: true } },
};
</script>

更改AddressForm.vueOtherForm.vue 中输入字段的值将触发道具突变警告。我想知道如何在不改变道具的情况下与表单进行上下交流?

我已经提出了可能的解决方案,但我不知道我应该选择哪一个(以及如何实施)

  • created() 中克隆formData 属性并将v-model 链接到本地​​克隆的formData 而不是属性。然后观察克隆的formData 并在每次值更改时发出。
  • 使用 v-model 而不是 props 进行绑定

【问题讨论】:

    标签: javascript vue.js


    【解决方案1】:

    使用v-model 将您的子表单设置为custom inputs,而不是传递道具:

    AddressForm.vue

    <template>
      <div>
        <input :value="value.address_no" @input="$emit('input',{...value,address_no:$event.target.value)" />
        <input :value="value.country" @input="$emit('input',{...value,country:$event.target.value)" />
      </div>
    </template>
    
    <script>
    export default {
      name: "AddressForm",
      props: { value: { type: Object, required: true } },
    };
    </script>
    

    其他形式:

    <template>
      <div>
        <textarea :value="value.remarks" @input="$emit('input',{...value,remarks:$event.target.value)"/>
      </div>
    </template>
    
    <script>
    export default {
      name: "OtherForm",
      props: { value: { type: Object, required: true } },
    };
    </script>
    

    在父组件中:

        <AddressForm v-model="formData.address" />
        <OtherForm v-model="formData.other" />
    

    【讨论】:

    • 谢谢,我还有一个问题 - 在每个 @input 上发射对我来说不是很理想(我正在处理一个非常大的表单)。有没有办法优化这个?
    • 我很高兴,将lazy 修饰符添加到v-model 指令,如&lt;OtherForm v-model.lazy="formData.other" /&gt;
    【解决方案2】:

    您可以在beforeMount() 中将这些道具分配给一些数据值,然后将它们 $emit 回来。
    显然v-model应该是指data()中定义的属性。

    【讨论】:

    • 谢谢,你能举个例子吗?
    猜你喜欢
    • 2021-09-27
    • 2020-11-30
    • 2020-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-24
    • 2011-02-16
    • 2016-11-19
    相关资源
    最近更新 更多