Vue3父子组件中关于ref和emit的一些问题

这是UpdateAvatar.vue子组件:

<template>
    <div>
        <Dialog :show="dialogConfig.show" :title="dialogConfig.title" :buttons="dialogConfig.buttons" width="500px"
            :showCancel="false" @close="dialogConfig.show = false">
            <el-form :model="formData" ref="formDataRef" label-width="80px" @submit.prevent>
                <!--昵称-->
                <el-form-item label="昵称">
                    {{ formData.nickName }}
                </el-form-item>
                <!--头像-->
                <el-form-item label="头像">
                    <AvatarUpload v-model="formData.avatar"></AvatarUpload>
                </el-form-item>
            </el-form>
        </Dialog>
    </div>
</template>

<script setup>

......

const api = {
    ......
};

const formData = ref({});
const formDataRef = ref();

const show = (data) => {
	......
};

defineExpose({ show });

const dialogConfig = ref({
    ......
});
const emit = defineEmits();
const submitForm = async ()=>{
    if(!(formData.value.avatar instanceof File)){
        dialogConfig.value.show = false;
        return;
    }
    let result = await proxy.Request({
        url: api.updateUserAvatar,
        params: {
            avatar: formData.value.avatar,
        },
    });
    if(!result){
        return;
    }
    dialogConfig.value.show = false;
    const cookieUserInfo = proxy.VueCookies.get("userInfo");
    delete cookieUserInfo.avatar;
    proxy.VueCookies.set("userInfo", cookieUserInfo, 0);
    emit("updateAvatar");
}

</script>

<style lang="scss" scoped></style>

这是在父组件中调用UpdateAvatar组件的语法:

<UpdateAvatar ref="updateAvatarRef" @updateAvatar="reloadAvatar"></UpdateAvatar>

问题1:ref="UpdateAvatarRef"的作用?

在父组件中使用 ref=“UpdateAvatarRef”,它的作用是通过 ref 获取子组件 UpdateAvatar 的实例,从而可以在父组件中直接调用子组件的属性或方法。在这个例子中,<UpdateAvatar ref=“UpdateAvatarRef” 给 UpdateAvatar 组件加上了一个 ref 标识,父组件可以获取该组件的实例。这种方式使得父组件可以控制子组件中的行为,比如动态地设置头像数据,或触发组件内的业务逻辑。

问题2:emit(“updateAvatar”)的作用?

emit(“updateAvatar”) 是用来在子组件中触发自定义事件 updateAvatar 的。在 Vue 组件中,emit 用来向父组件发送事件通知。
在你的代码中,emit(“updateAvatar”) 的作用是,当头像修改成功后,向父组件发送 updateAvatar 事件通知。父组件在接收到这个事件后,会执行相应的回调函数来处理后续逻辑。
例如,父组件使用 @updateAvatar=“reloadAvatar”,意思是在 UpdateAvatar 组件触发 updateAvatar 事件时,父组件会执行 reloadAvatar 方法。这个方法可以用于更新头像信息或执行其他需要在头像修改后完成的操作。
工作流程:
子组件 UpdateAvatar 中执行 submitForm,当头像上传成功后,调用 emit(“updateAvatar”)。
触发父组件监听的 updateAvatar 事件。
父组件捕捉到事件,执行 reloadAvatar 方法,可能是用于重新加载头像或更新用户界面。

附加问题:
AvatarUpload子组件方法:

const uploadImage = async (file) => {
  file = file.file;
  let img = new FileReader();
  img.readAsDataURL(file);
  img.onload = ({ target }) => {
    localFile.value = target.result;
  };
  emit("update:modelValue", file);
};

父组件AvatarUpload引用:

<AvatarUpload v-model="formData.avatar"></AvatarUpload>

emit(“update:modelValue”, file)作用?

在 AvatarUpload 子组件中,emit(“update:modelValue”, file) 的作用是更新父组件传递的 v-model 绑定的值。
具体过程:
1.v-model 的双向绑定: 当你在父组件中使用 v-model=“formData.avatar” 来绑定 AvatarUpload 子组件时,它实际上是 Vue 处理的语法糖。Vue 会将 v-model 转换为一个 :modelValue 绑定和一个 @update:modelValue 事件监听器的组合。
所以等效的代码是:
<AvatarUpload :modelValue=“formData.avatar” @update:modelValue=“formData.avatar = $event”>
2.emit(“update:modelValue”, file) 的作用: 当 emit(“update:modelValue”, file) 在子组件中被调用时,它会触发 update:modelValue 事件,并将 file 作为参数传递给父组件。在父组件中,Vue 会自动捕获这个事件并将 formData.avatar 的值更新为 file,实现数据的双向绑定。
3.效果:
当用户在 AvatarUpload 组件中上传图片时,file 是上传的文件对象。
emit(“update:modelValue”, file) 会通知父组件更新 formData.avatar,将上传的文件赋值给 formData.avatar。
这样,formData.avatar 的值会随着用户上传图片而自动更新。
emit(“update:modelValue”, file) 的作用是将子组件内部上传的文件 file 传递给父组件,并更新父组件中 v-model 绑定的 formData.avatar。这实现了子组件与父组件之间的双向数据绑定。

上一篇:红队-安全见闻篇(下)


下一篇:Flutter &鸿蒙next中的路由使用详解【基础使用】