Vue3.0组合式API:使用defineEmits()实现子组件向父组件传递数据

news/2024/9/19 13:56:39 标签: vue.js, 前端, javascript

1、使用 defineEmits() 函数

父组件通过使用 Prop 为子组件传递数据,但如果子组件要把数据传递回去,就需要使用自定义事件来实现。父组件可以通过 v-on 指令(简写形式“@”)监听子组件实例的自定义事件,而子组件可以通过调用内建的 defineEmits() 函数并传入事件名称来触发自定义事件。

使用 <script setup> 语法糖,<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。在 Vue3.2 中只需要在 script 标签上加上 setup 属性,无需 return,template 便可直接使用。相比于普通的 <script> 语法,它具有更多优势。

Vue3.0组合式API,组件之间的数据传递:

父传子:使用 defineProps() 函数。

子传父:使用 defineEmits()​ 函数。

为了在声明 props 和 emits 选项时获得完整的类型推导支持,我们可以使用 defineProps() 函数  和 defineEmits() 函数 API,它们将自动地在 <script setup> 中可用:

<script setup>
//父传子
const props = defineProps({
  foo: String
})

//子传父
const emit = defineEmits(['change', 'delete'])
// setup 代码
</script>
  1. defineProps() 函数 和 defineEmits() 函数 都是只能在 <script setup> 中使用的编译器宏。他们不需要导入,且会随着 <script setup> 的处理过程一同被编译掉。
  2. defineProps() 函数 接收与 props 选项相同的值,defineEmits() 函数 接收与 emits 选项相同的值。
  3. defineProps() 函数 和 defineEmits() 函数 在选项传入后,会提供恰当的类型推导。
  4. 传入到 defineProps() 函数 和 defineEmits() 函数 的选项会从 setup 中提升到模块的作用域。因此,传入的选项不能引用在 setup 作用域中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块作用域内。

defineEmits()​ 函数的语法格式如下:

javascript">defineEmits( eventName, […args] )

参数说明:

eventName:传入事件的名称。

 […args]:触发事件传递的参数,该参数是非必选。

【实例】在 <script setup> 语法糖中,使用 defineEmits() 函数,实现子组件向父组件传递数据。

(1)创建 ParentComponent.vue 父组件

<template>
    <fieldset>
        <legend>父组件</legend>
        <h3>父组件接收到子组件传递的数据:</h3>
        <p>博客信息:{{ blogInfo.blogName }}</p>
        <p>博客信息:{{ blogInfo.blogUrl }}</p>

        <!-- 使用组件 -->
        <ChildComponent @receiverData="getBlogInfo" />
    </fieldset>
</template>

<!-- 使用 <script setup> 语法糖 -->
<script setup>
import { reactive } from 'vue';

//引用组件,使用 <script setup> 语法糖引用的组件会自动执行注册
import ChildComponent from '@/components/ChildComponent.vue'

// 使用 reactive 创建响应式的对象
const blogInfo = reactive({});

// 核心代码:接收子组件传递数据的方法
function getBlogInfo(blogName, blogUrl) {
    blogInfo.blogName = blogName;
    blogInfo.blogUrl = blogUrl;
}

</script>

(2)创建 ChildComponent.vue 子组件

<template>
    <fieldset>
        <legend>子组件</legend>
        <button @click="sendData">传递数据给父组件</button>
    </fieldset>
</template>

<!-- 使用 <script setup> 语法糖 -->
<script setup>
import { reactive } from 'vue';

// 使用 reactive 创建响应式的对象
const blogInfo = reactive({
    blogName: '您好,欢迎访问 pan_junbiao的博客',
    blogUrl: 'https://blog.csdn.net/pan_junbiao'
});

//核心代码
const emit = defineEmits(['receiverData']);

function sendData() {
    //核心代码:触发自定义事件,传递数据个父组件
    emit('receiverData', blogInfo.blogName, blogInfo.blogUrl);
}

</script>

 (3)在 App.vue 根组件中,引入父组件

<template>
  <!-- 使用组件 -->
  <ParentComponent />
</template>
 
<script setup>
//引用组件,使用 <script setup> 语法糖引用的组件会自动执行注册
import ParentComponent from '@/components/ParentComponent.vue';

</script>

执行结果:

2、组件事件配合 v-model 指令

如果是在子组件中用户输入数据,我们希望在获取数据的同时发生数据给父组件,这是可以配合 v-model 指令使用。

【实例】子组件中用户输入数据,在父组件中实时获取数据。

(1)修改 ParentComponent.vue 父组件

<template>
    <fieldset>
        <legend>父组件</legend>

        <!-- 使用组件 -->
        <ChildComponent @searchEvent="getSearch" />

        <h3>父组件接收到子组件传递的数据:</h3>
        接收到的搜索关键字:<input type="text" v-model="search" />
    </fieldset>
</template>

<!-- 使用 <script setup> 语法糖 -->
<script setup>
import { ref } from 'vue';

//引用组件,使用 <script setup> 语法糖引用的组件会自动执行注册
import ChildComponent from '@/components/ChildComponent.vue'

// 使用 ref 创建响应式的对象
const search = ref('');

// 核心代码:接收子组件传递数据的方法
function getSearch(keyword) {
    search.value = keyword;
}

</script>

<style>
input {
    width: 300px;
    padding: 3px;
    font-size: 16px;
}
</style>

(2)修改 ChildComponent.vue 子组件

<template>
    <fieldset>
        <legend>子组件</legend>
        搜索:<input type="text" v-model="search" />
    </fieldset>
</template>

<!-- 使用 <script setup> 语法糖 -->
<script setup>
import { ref, watch } from 'vue';

// 使用 ref 创建响应式的对象
const search = ref('');

//核心代码
const emit = defineEmits(['searchEvent']);

//watch监听器
watch(search, (newValue, oldValue) => {
    //核心代码:触发自定义事件,传递数据个父组件
    emit('searchEvent', newValue);
});

</script>

执行结果:


http://www.niftyadmin.cn/n/5665644.html

相关文章

线程池的状态

线程池的状态分为&#xff1a;Running(运行状态)、Shutdown(关闭状态)、Stop(停止状态)、Tidying(整理状态)、Terminated(终止状态)。 Running(运行状态)&#xff1a;线程池被创建时&#xff0c;就是Running状态&#xff0c;线程池中的任务数位0。 该状态会接受新任务&#xf…

Docker指令学习1

docker指令 查看镜像列表&#xff1a; docker images | docker image ls 删除单个镜像: docker rmi <image_name>: 强制删除镜像&#xff1a; docker rmi -f <image_id> 如果镜像正在被某些容器使用&#xff0c;普通删除命令会失败。使用 -f 选项强制删除镜像 注意…

手语识别系统源码分享

手语识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

数据结构-3.链表

前言 本篇博客给大家带来的是链表的知识点, 其中包括面试经常会提问的真题 ArrayList 和 LinkedList 的区别 . 文章专栏: Java-数据结构 若有问题 评论区见 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条, 如果分享不成功, 那我就会回你一下,那样你就分享成…

javascript-装饰器

装饰器 装饰者模式&#xff1a;能够在不改变对象自身基础上&#xff0c;在程序运行期间给对象添加职责 装饰器只能针对类和类的属性&#xff0c;不能直接作用于函数&#xff08;由于存在函数提升&#xff09; 本质上是语法糖&#xff0c;借助 Object.defineProperty(target,na…

WEB 编程:使用富文本编辑器 Quill 配合 WebBroker 后端

使用 Delphi 的 WebBroker 框架写 Web Server&#xff0c;需要一个前端的富文本编辑器。 评估了好几个&#xff0c;最后选择 Quill 这个开源的。 官方地址&#xff1a;Quill - Your powerful rich text editor 把前端代码&#xff0c;存储为一个单独的文本文件&#xff0c;方…

AI产品经理面试的问题和回复建议

如果你正在考虑找AI产品经理的岗位工作&#xff0c;建议好好准备以下的面试问题&#xff1a; 关于面试时间&#xff1a;一般AI产品经理的面试时间在40分钟-70分钟左右&#xff0c;主要看面试官是否对你感兴趣&#xff08;你的产品经验、气场是否相符&#xff09;。时间越长一般…

《拿下奇怪的前端报错》:nvm不可用报错`GLIBC_2.27‘‘GLIBCXX_3.4.20‘not Found?+ 使用docker构建多个前端项目实践

有些前端的小伙伴可能会好奇&#xff0c;nvm是什么&#xff1f;这里接简单介绍下&#xff0c;它是一个Nodejs版本管理工具。为什么需要它呢&#xff1f;当然是需要多个Nodejs版本的时候&#xff0c;那什么时候需要多个Nodejs版本&#xff1f;那肯定是在有点年头的公司了&#x…