木灵鱼儿

木灵鱼儿

阅读:528

最后更新:2022/08/16/ 1:21:58

vue3 emits 自定义事件声明

在vue2的时候,我们的自定义事件是通过this.$emit进行触发的,并没有统一的某一处属性进行定义,这其实会导致一个问题,当代码量上升一定程度后,后面来维护的人很难快速了解这个组件的自定义事件有哪些。

vue3版本提供了emits配置,它可以定义当前组件触发的自定义事件有哪些,并且还支持参数校验,如果绑定的事件没有在emits中显式声明,那么就会作为$attrs属性挂载到根节点上,这个效果在fragment组件是无效的。

为此vue3放弃了.native修饰符,一方面是因为emits的存在,可以更加明确的知道该组件支持什么自定义事件,另一方面是因为未声明的事件会默认绑定到根节点上,所以.native已经可有可无了,它的作用本身也是将事件绑定到组件的根节点上而已。

如果不想让未声明的事件会默认绑定到根节点上,可以给组件配置inheritAttrs: false,关闭继承属性,这个功能在vue2中也存在,就不细说了。关键字:透传

普通用法

子组件

<template>
  <button @click="onClick">aaa</button>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  emits: ["click"],
  setup(props, { emit }) {
    function onClick() {
      emit("click", "test");
    }

    return {
      onClick,
    };
  },
});
</script>

父组件

<template>
  <div>
    <test @click="onClick" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import test from "./components/test.vue";

export default defineComponent({
  setup() {
    function onClick(val: string) {
      console.log(val);
    }
    return {
      onClick,
    };
  },
  components: {
    test,
  },
});
</script>

使用上出来emit是通过setup参数获取之外,其他并没有什么不同。

注意

如果子组件没有在emits中声明click事件,那么当我们点击btn按钮的时候,click会触发两次,所以一定要注意,自定义事件一定要在emits中声明。

这两次事件分别是由:

  1. emit触发
  2. 子组件根元素的click事件

而且我们不推荐emits中使用原生事件的名称,建议是自己编一个事件名,比如:myClick

当然,这个触发两次在vue2中并不会出现。

参数校验

从官方的类型定义上看

interface ComponentOptions {
  emits?: ArrayEmitsOptions | ObjectEmitsOptions
}

type ArrayEmitsOptions = string[]

type ObjectEmitsOptions = { [key: string]: EmitValidator | null }

type EmitValidator = (...args: unknown[]) => boolean

使用数组,那么事件名全都是string类型,如果使用键值对,那么就可以声明一个校验函数,来进行参数校验,这个校验函数接的参就是我们emit触发时传的参,当我们校验后返回一个布尔值,如果不return布尔值,那么默认是undefined
,转为布尔值就是false,所以这个需要注意。

目前这个参数校验并不会阻断我们的事件触发,当校验函数返回的是false的时候,也仅仅是在控制台输出一段警告,我们也可以自己手动打印一个警告,虽然官方推荐使用,但是好似没有太大的功能性提升,如果能阻断事件,我觉得会是一个很好的功能,但是目前没有这么做。

所以,目前数组形式的emits是常见的做法。

<template>
  <button @click="onClick">aaa</button>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  emits: {
    click: (val: string) => {
      if (val !== "test") {
        return false;
      }
      return true;
    },
  },
  setup(props, { emit }) {
    function onClick() {
      emit("click", "test");
    }

    return {
      onClick,
    };
  },
});
</script>

版权申明

本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。

关于作者

站点职位 博主
获得点赞 0
文章被阅读 528

相关文章