vue,vue3中emit解析

Vue父子组件通信:通过信号实现数据更新
文章讲述了在Vue中,父子组件间的通信是单向的,子组件通过`emit`发送信号通知父组件,父组件接收到信号后执行相应函数。例子中,子组件的点击事件触发`emit(showWin,true)`,父组件通过`showWin`接收并执行`upWin`函数。

emit:

父子组件的耦合纽带,子组件不能修改父组件的数据

如需要修改,通过某个信号去通知父组件更新,再传递到子组件

具体解释:父组件注册了一个函数,但是它不会自己去执行这个函数,它需要收到一个信号才会自己去执行。什么叫注册了一个函数呢?说白了,就是它在自己本身组件内部定义了一个函数,但是这个函数在没有收到 “信号的时候是不会去执行的”。
 

如果你能明白上一段的意思,那么你基本上就知道 “信号” 究竟是谁发出来的了。让我们回到子组件内部,在子组件内,我们需要去拿到父组件注册的那个函数名字。也就是showWin,来准备通知父组件。

子组件 child.vue

 点击按钮,触发函数onCloseds,函数发出信号通知父组件更新 emit("showWin",true)

<template>
  <button @click="onCloseds">请更新数据</button>
<template>

<script setup>  
    import {defineEmits} from 'vue'
    const emit  = defineEmits(['showWin'])
    const onCloseds = () => {
        emit("showWin",true)
    }
</script>

父组件parent.vue

父组件接受到信号showWin,执行函数upWin去更新数据

<template>
  <Child @showWin="upWin"></Child>
</template>

<script setup>
import Child from './Child.vue'
const upWin = ((isflag) => {
  console.log('子组件通知我更新啦!)
})
</script>

<think>在Vue 3中,组件之间通信的一种常见方式是使用自定义事件。子组件可以通过`$emit`方法触发一个自定义事件,并传递数据给父组件。父组件则可以在使用子组件的地方通过`v-on`(或简写为`@`)来监听这个事件,并执行相应的处理函数。 下面是一个简单的例子,展示如何在Vue 3中使用`$emit`: ### 子组件(ChildComponent.vue) 在子组件中,我们有一个按钮,当点击按钮时,会触发一个名为`custom-event`的事件,并传递一个字符串数据。 ```vue <template> <button @click="handleClick">点击我触发事件</button> </template> <script> export default { methods: { handleClick() { // 触发一个名为&#39;custom-event&#39;的事件,并传递数据 this.$emit(&#39;custom-event&#39;, &#39;这是来自子组件的数据&#39;); } } } </script> ``` ### 父组件(ParentComponent.vue) 在父组件中,我们使用子组件,并通过`@custom-event`监听子组件触发的`custom-event`事件。当事件被触发时,调用`handleCustomEvent`方法,并将子组件传递的数据作为参数。 ```vue <template> <div> <ChildComponent @custom-event="handleCustomEvent" /> <p>接收到的数据:{{ receivedData }}</p> </div> </template> <script> import ChildComponent from &#39;./ChildComponent.vue&#39;; export default { components: { ChildComponent }, data() { return { receivedData: &#39;&#39; }; }, methods: { handleCustomEvent(data) { this.receivedData = data; // 将子组件传递的数据赋值给receivedData } } } </script> ``` ### 解释 1. **子组件**:当按钮被点击时,调用`handleClick`方法,该方法使用`this.$emit(&#39;custom-event&#39;, ...)`触发一个自定义事件,并传递数据。 2. **父组件**:在模板中使用子组件时,通过`@custom-event`监听这个事件,并绑定到`handleCustomEvent`方法。当子组件触发事件时,父组件的方法被调用,并将传递的数据赋值给`receivedData`,然后在模板中显示。 ### 使用`defineEmits`(Vue 3.2+ 的Composition API写法) 在Vue 3.2+中,如果你使用`<script setup>`语法糖,推荐使用`defineEmits`来声明事件。这样代码更清晰,并且有更好的类型支持(如果使用TypeScript)。 #### 子组件(使用Composition API) ```vue <template> <button @click="handleClick">点击我触发事件</button> </template> <script setup> import { defineEmits } from &#39;vue&#39;; // 定义要触发的事件 const emit = defineEmits([&#39;custom-event&#39;]); const handleClick = () => { emit(&#39;custom-event&#39;, &#39;这是来自子组件的数据(Composition API)&#39;); }; </script> ``` #### 父组件 父组件的使用方式不变,仍然通过`@custom-event`监听事件。 ### 注意事项 - 事件名:推荐使用kebab-case(短横线分隔)的事件名,因为在DOM模板中,事件名会被自动转换为小写。在父组件中使用时,必须使用与子组件中触发事件时完全相同的事件名(包括大小写,但建议统一使用kebab-case)。 - 传递多个参数:如果需要传递多个参数,可以传递一个对象,或者按顺序传递多个参数。在父组件中接收时,方法定义对应的参数即可。 ### 传递多个参数的例子 子组件: ```javascript this.$emit(&#39;custom-event&#39;, &#39;参数1&#39;, 2, { key: &#39;value&#39; }); ``` 父组件: ```vue <ChildComponent @custom-event="(arg1, arg2, arg3) => handleCustomEvent(arg1, arg2, arg3)" /> ``` 或者定义一个方法来接收多个参数: ```javascript methods: { handleCustomEvent(arg1, arg2, arg3) { // 处理参数 } } ``` ### 使用事件验证(Composition API) 在Composition API中,使用`defineEmits`时,还可以对事件参数进行验证: ```vue <script setup> const emit = defineEmits({ // 验证事件,返回布尔值表示参数是否有效 &#39;custom-event&#39;: (param1, param2) => { // 做一些验证 return param1 !== &#39;&#39; && param2 > 0; } }); </script> ``` 这样,在触发事件时,如果验证不通过,会在开发环境下给出警告。 ### 总结 在Vue 3中,`$emit`仍然是子组件向父组件通信的重要方式。在Options API中,我们使用`this.$emit`;在Composition API中,我们使用`defineEmits`来定义和触发事件。父组件通过`v-on`或`@`来监听子组件触发的事件。 §§相关问题§§: 1. Vue 3中,除了`$emit`,还有哪些组件通信方式? 2.Vue 3的Composition API中,如何使用`defineEmits`定义多个事件? 3. 如何在Vue 3中实现跨组件通信(例如兄弟组件通信)? 4. Vue 3中,如何监听子组件触发的原生事件(如click)?</think>在 Vue 3 中,使用 `$emit` 的基本原理与 Vue 2 相同,但 Composition API 提供了更灵活的方式。以下是详细实现和案例: ### 基础用法 (Options API) ```vue <!-- 子组件 ChildComponent.vue --> <template> <button @click="notifyParent">通知父组件</button> </template> <script> export default { methods: { notifyParent() { // 触发自定义事件并传递数据 this.$emit(&#39;custom-event&#39;, { message: &#39;Hello from child!&#39;, value: 42 }) } } } </script> ``` ```vue <!-- 父组件 ParentComponent.vue --> <template> <ChildComponent @custom-event="handleEvent" /> <p>接收到的消息: {{ receivedMessage }}</p> <p>接收到的值: {{ receivedValue }}</p> </template> <script> import ChildComponent from &#39;./ChildComponent.vue&#39; export default { components: { ChildComponent }, data() { return { receivedMessage: &#39;&#39;, receivedValue: null } }, methods: { handleEvent(payload) { this.receivedMessage = payload.message this.receivedValue = payload.value console.log(&#39;收到子组件数据:&#39;, payload) } } } </script> ``` ### Composition API 写法 ```vue <!-- 子组件 ChildComponent.vue --> <template> <button @click="emitEvent">使用Composition API触发</button> </template> <script setup> import { defineEmits } from &#39;vue&#39; // 定义可触发的事件 const emit = defineEmits([&#39;custom-event&#39;, &#39;another-event&#39;]) const emitEvent = () => { // 触发带验证的事件 emit(&#39;custom-event&#39;, { timestamp: new Date(), data: &#39;Composition API payload&#39; }) // 触发另一个事件 emit(&#39;another-event&#39;, &#39;简单数据&#39;) } </script> ``` ```vue <!-- 父组件 ParentComponent.vue --> <template> <ChildComponent @custom-event="handleCustomEvent" @another-event="handleAnotherEvent" /> </template> <script setup> import { ref } from &#39;vue&#39; import ChildComponent from &#39;./ChildComponent.vue&#39; const lastEvent = ref(null) const handleCustomEvent = (payload) => { console.log(&#39;自定义事件数据:&#39;, payload) lastEvent.value = payload } const handleAnotherEvent = (data) => { console.log(&#39;另一个事件:&#39;, data) } </script> ``` ### 带类型验证的 emit (TypeScript) ```vue <!-- 子组件 ChildComponent.vue --> <script setup lang="ts"> const emit = defineEmits({ // 带验证函数emit &#39;validated-event&#39;: (payload: { id: number; name: string }) => { // 返回布尔值表示验证是否通过 return payload.id > 0 && payload.name.length > 0 }, // 简单事件 &#39;simple-event&#39;: null }) const sendValidData = () => { emit(&#39;validated-event&#39;, { id: 1, name: &#39;Valid Data&#39; }) // 成功 // emit(&#39;validated-event&#39;, { id: 0, name: &#39;&#39; }) // 开发环境会警告 } </script> ``` ### 关键点解释: 1. **defineEmits**:在 `<script setup>` 中替代 `this.$emit`,提供更好的类型支持 2. **事件验证**:可添加验证函数确保传递数据的正确性 3. **多事件触发**:一个组件可以定义和触发多个自定义事件 4. **类型安全**:TypeScript 用户可享受完整的类型推断 5. **事件命名**:推荐使用 kebab-case (短横线命名) 如 `update-value` ### 最佳实践: 1. 使用描述性事件名 (如 `update:title` 而非 `change`) 2. 复杂数据使用对象包装 3. 对于 v-model 双向绑定,使用 `update:modelValue` 特殊事件名 4. 在大型项目中为事件定义类型接口
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值