【问题标题】:VueJs 3 emit event from grand child to his grand parent componentVueJs 3 将事件从孙子发送到他的祖父组件
【发布时间】:2023-01-07 03:42:57
【问题描述】:

我是 Vue 的新手,正在做我的第一个项目。我正在创建一个包含多个子组件和孙组件的表单。我遇到了一个问题,我需要能够生成多个表单副本。因此,我将一些数据属性上移了 1 级。目前,表单是ApplicationPage.Vue > TheApplication.Vue > PersonalInformation.Vue > BaseInput.Vue。我的问题是我需要通过 TheApplication 发出从 PersonalInformation 到 ApplicationPage 的更改。我很难弄清楚如何处理这种情况。我一直在寻找适用于 Vue2 但不是适用于 Vue3 的解决方案。

应用页面.vue

template
      <TheApplication :petOptions="petOptions"
                      :stateOptions='stateOptions'
                      v-model="data.primary"
                      applicant="Primary"/>

script
data() {
    return {
      data: {
        primary: {
          personalInformation: {
            first_name: "",
            middle_name: "",
            last_name: "",
            date_of_birth: "",
            phone: null,
            email: "",
            pets: "",
            driver_license: null,
            driver_license_state: "",
            number_of_pets: null,
            additional_comments: ""
          },
        },
      },
    }
  },

应用程序.Vue

            <personal-information :petOptions="petOptions"
                                  :stateOptions='stateOptions'
                                  :personalInformation="modelValue.personalInformation"
                                  @updateField="UpdateField"
            />
  methods: {
    UpdateField(field, value) {
      this.$emit('update:modelValue', {...this.modelValue, [field]: value})
    },

个人信息.vue

      <base-input :value="personalInformation.first_name"
                  @change="onInput('personalInformation.first_name', $event.target.value)"
                  label="First Name*"
                  type="text" class=""
                  required/>
methods: {
    onInput(field, value) {
      console.log(field + " " + value)
      // this.$emit('updateField', { ...this.personalInformation, [field]: value })
      this.$emit('updateField', field, value)
    },
  }

【问题讨论】:

    标签: vue.js vue-component vuejs3


    【解决方案1】:

    我会这样做:codesandbox

    发射只有两个参数,发射的名称和发射的值。如果发出多个值,则必须将这些值作为单个对象发出。 在我的解决方案中,孙组件将字段名称和值作为单个对象发出

    孙子

    <input
        :value="personalInformation.first_name"
        @input="onInput('first_name', $event.target.value)"
        ...
    >
    
    onInput(field, value) {
      this.$emit("update-field", { field: field, value: value });
    },
    

    子对象捕获并重新发出,首先注意以父组件期望的格式发出(它期望整个 data.primary 对象,因为这是设置为 v-model 的对象)

    孩子

    <grandchild
        :personalInformation="modelValue.personalInformation"
        @updateField="UpdateField"
      />
    
    UpdateField({ field, value }) {
      const newVal = this.modelValue;
      newVal.personalInformation[field] = value;
      this.$emit("update:modelValue", newVal);
    }
    

    然后父组件自动接收并更新 v-model data.primary 对象。

    或者,我不得不提一下,你可以随时使用 Vue 的官方状态管理库 Pinia,而不是处理任何在多个级别的组件之间发出/传递对象(在一个组件中保存一些状态,从任何组件读取相同的状态其他成分)。当然有一个学习曲线,但它绝对值得学习,并且旨在简化这种情况。

    【讨论】:

    • 谢谢!我正要使用状态管理,但我觉得这太过分了,因为数据只需要在一条直线上。
    • 有没有办法可以向@updateField="UpdateField" 添加一个附加参数?我还有 2 个其他子组件,其中包含数组,我需要传递索引位置,以便我可以更新正确的字段。
    • @Mwheeler91 是的,这里的商店可能有点矫枉过正。至于额外的参数,你可以添加几乎所有你想要的newVal。把你想要的任何变量放在那里,你不需要只使用 UpdateField 正在接收的内容 (field + value)。
    【解决方案2】:

    对于不想链接事件发出的任何人,子对象上有父对象也可用于发出事件。请务必在父级中注册发射以避免在控制台中出现警告。

    孩子

    在此处致电直系父母的$emit

    儿童.vue

    <input @input="$parent.$emit('custom-event', e.target.value) />
    
    

    或者使用方法:

    <input @input="handleInput" />
    
    export default {
      methods: {
        handleInput(e) {
          this.$parent.$emit('custom-event', e.target.value)
        }
      }
    }
    

    家长

    由于是父级向祖先发出发射,因此请在此处声明发射。对于&lt;script setup&gt;,只需使用defineEmits() 方法来声明发射。请参阅docs

    父母观

    <Child /> <!-- No need to listen to the event here -->
    
    export default {
       emits: ['custom-event'] // Register the emits
    }
    

    如果使用&lt;script setup&gt;

    <script setup>
      defineEmits(['custom-event']) // Register the emits
    </script>
    

    祖父母

    然后监听祖父母组件中的事件。

    祖父母.vue

     <Parent @custom-event="doSomething()" /> <!-- The event is being listened to in the grandparent component -->
    

    【讨论】:

      猜你喜欢
      • 2019-01-10
      • 2021-02-12
      • 2022-08-02
      • 2018-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多