我对 Vue 比较陌生,正在开发我的第一个项目。我正在努力创建一个包含多个子组件和孙组件的表单。我遇到了一个问题,我需要能够生成表单的多个副本。因此,我将一些数据属性上移了 1 级。目前,表单为ApplicationPage.Vue > TheApplication.Vue > PersonalInformation.Vue > BaseInput.Vue。我的问题是我需要通过 TheApplication 发出从 PersonalInformation 到 ApplicationPage 的更改。我很难弄清楚如何处理这种情况。我一直在寻找 Vue2 的解决方案,但没有找到 Vue3 的解决方案。
ApplicationPage.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: "" }, }, }, } },
TheApplication.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) }, }
P粉0378809052023-11-04 14:55:06
对于任何不想链接事件发出的人,子对象上都有父对象,它也可用于发出事件。请务必在父级中注册发射,以避免控制台中出现警告。
在此处调用直接父级的 $emit
。
Child.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) } } }
由于是父级向祖先发出信号,因此请在此处声明发射。对于 ,只需使用
defineEmits()
方法来声明发射。请参阅文档。
Parent.vue
<Child /> <!-- No need to listen to the event here -->
export default { emits: ['custom-event'] // Register the emits }
如果使用<脚本设置>
<script setup> defineEmits(['custom-event']) // Register the emits </script>
然后在祖父母组件中监听事件。
GrandParent.vue
<Parent @custom-event="doSomething()" /> <!-- The event is being listened to in the grandparent component -->
P粉8422150062023-11-04 12:19:54
这就是我的做法: codesandbox< /a>
Emits 仅接受两个参数,即发出的名称和发出的值。如果发出多个值,则必须将这些值作为单个对象发出。 在我的解决方案中,孙组件将字段名称和值作为单个对象发出
孙子
<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 模型的内容)
孩子
<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
对象。
或者,我必须提到,您始终可以使用Pinia,Vue 的官方状态管理库(在一个组件中保存一些状态,从任何其他组件读取相同的状态)。当然有一个学习曲线,但它绝对值得学习,并且正是为了简化这种类型的情况。