前言:不懂在父组件里对子组件 @xxxx 声明自定义事件,就不用看本篇文章了。本篇对此内容不做任何说明。这是与 emits 结合使用的必备知识!

<childComp @emitEvnentName='deleteFn'></childComp>

emits

场景说明:

组件功能封装:
        组件封装了一系列 emit 事件,并返回数据、回调函数等,或单纯执行某个操作后,触发父组件的事件响应。
        外部要用时,使用 @xxxx 来接收使用、响应。

  • 类型:Array<string> | Object

  • 详细:

    emits 可以是数组或对象,从组件触发自定义事件,emits 可以是简单的数组,也可以是对象,后者允许配置事件验证。

    在对象语法中,每个 property 的值可以为 null 或验证函数。验证函数将接收传递给 $emit 调用的其他参数。如果 this.$emit('foo',1) 被调用,foo 的相应验证函数将接收参数 1。验证函数应返回布尔值,以表示事件参数是否有效。

数组写法:// emits:['emitEvnentName']

对象写法:// emits:{}
        { eventName:null }
        { eventName:()=>{} }


细节说明:

1、数组形式和对象形式的值为null,表示该emit事件无验证函数。
2、对象形式且值为函数表示该 emit 配置了事件验证
        验证函数必须有 return 真假值,真值表示通过验证,假值则 vue 会自动抛出 warn 警告!不 return 值默认当做失败,抛出 warn 警告!
        验证函数主要就是验证参数是否正确,并不会在 return false 时中断 emit() 事件!

// 子组件
<template>
    <el-button type="success" plain @click='trigger'>emits测试</el-button>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  // 定义自定义事件
  // emits:['emitEvnentName'], // 数组写法都默认无验证函数!!
  emits: {
    noVerification: null, // 无验证函数

    emitEvnentName: ({ email, password },data2,dataX) => { 
      console.log('定义自定义事件-myEvent',email, password,data2,dataX);
      if (email && password) {

        // 验证函数应返回布尔值,以表示事件参数是否有效。
        return true

      } else {
        console.error('Invalid submit event payload!')
        return false
      }
    }
  },
  methods:{
    trigger(){
      let email = 1
      let password = null
      this.$emit('emitEvnentName',{email, password},'data2',['data3','data4'])
    }
  }
})
</script>


$emit

  • 参数:

    • {string} eventName
    • [...args]

    触发当前实例上的事件。附加参数都会传给监听器回调。

父组件自定义的事件名作为$emit的第一个参数,第二个参数开始就是传给绑定事件的参数,可以传多个参数。
其他没啥好说的了。。就只是触发事件罢了。

使用方法:(结合上面代码片段的案例,且父组件声明了 @emitEvnentName 自定义事件)
this.$emit('emitEvnentName',{email, password},'data2',['data3','data4'])



# composition Api 写法:defineEmits

在 <script setup> 中必须使用 defineProps 和 defineEmits API 来声明 props 和 emits ,它们具备完整的类型推断并且在 <script setup> 中是直接可用的:

<script setup>
const emit = defineEmits(['change', 'delete'])
</script>

defineEmits 是只在 <script setup> 中才能使用的编译器宏。他们不需要导入且会随着 <script setup> 处理过程一同被编译掉。

defineEmits 在选项传入后,会提供恰当的类型推断。

传入到 defineProps 和 defineEmits 的选项会从 setup 中提升到模块的范围。因此,传入的选项不能引用在 setup 范围中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块范围内。

以下为错误写法!!

let enFn = (val) => { 
    console.log('定义自定义事件-delete',val);
    if (val) {
      return true
    } else {
      console.error('Invalid submit event payload!')
      return false
    }
  }
const emit = defineEmits({
  noVerification: null, // 无验证函数
  delete: enFn // 会编译报错
})

defineEmits 也接收 emits 选项相同的值。效果跟options emits里的{} 一样,此处只展示写法,功能讲解的内容,忘了就请回看上面的 options 写法里的讲解!!

<script setup>
const emit = defineEmits({
  noVerification: null, // 无验证函数

  delete: (val) => { 
    console.log('定义自定义事件-myEvent',val);
    if (val) {
      return true

    } else {
      console.error('Invalid submit event payload!')
      return false
    }
  }
})
console.log(emit);

setTimeout(() => {
  emit('delete','测试')
}, 1000*10);
</script>

如果使用了 Typescript,使用纯类型声明来声明 prop 和 emits 也是可以的。 



# ts 类型声明写法:

defineProps 或 defineEmits 只能是要么使用运行时声明,要么使用类型声明。同时使用两种声明方式会导致编译报错。

讲解:左边的相当于函数参数名,第一个参数的值就是emit事件名,后面的任意多个参数都是emit事件的传递参数内容。剩下的就是TS相关内容,此处不对TS进行深入讲解,不懂的自己去学。


这里函数的参数名叫什么不重要,重要的是`ts类型`!第一个参数的ts类型值是`emit 事件名`,后面的参数 ts类型 则是emit传递的参数类型验证!提供编辑器报错功能。

<script setup lang='ts'>
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'delete', value: string, vlaue2:number ,value3?:boolean): void
}>()

setTimeout(() => {
  emit('delete', '123', 5666)
}, 1000*4);
</script>

使用类型声明的时候,静态分析会自动生成等效的运行时声明,以消除双重声明的需要并仍然确保正确的运行时行为。


场景说明:

组件功能封装:
        组件封装了一系列 emit 事件,并返回数据、回调函数等,或单纯执行某个操作后,触发父组件的事件响应。
        外部要用时,使用 @xxxx 来接收使用、响应。


QQ交流群:522976012  ,欢迎来玩

聚焦vue3,但不限于vue,任何前端问题,究其本质,值得讨论,研究与学习。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐