- 开始时间:2019-02-27
- 目标主要版本:2.x 和 3.x
- 引用 issue:N/A
- 实现的 PR:N/A
摘要
明确说明组件抛出的事件是什么。
基本范例
const Comp = {emits: {submit: payload => {// validate payload by returning a boolean}},created() {this.$emit('submit', {/* payload */})}}
动机
- 文档:与
props类似,明确的emits声明可以作为自我记录的代码。这对于其他开发者来说是非常有用的,他们可以立即了解该组件应该抛出什么事件。 - 运行时验证:该选项还提供了一种方法,对抛出的事件载荷(参数)进行运行时验证。
- 类型推断:emits 选项可以用于提供类型推断,以便
this.$emit和setupContext.emit调用可以被类型化。 - IDE 支持:当在组件上使用 v-on 监听器时,IED 可以利用 emits 选项来提供自动补全。
- 监听器 fallthrough 控制:随着提案的属性 fallthrough 更改,组件上的 v-on 监听器将默认为原生监听器。
emits提供了一种声明事件为组件专用的方法,以避免不必要的原生监听器的注册。
具体设计
引入了一个新的可选组件选项,名为 emits。
数组语法
对于简单的用例,选项值可以是一个包含字符串事件名称的数组:
{emits: ['eventA','eventB'}}
对象语法
或者它可以是一个以事件名称为 key 的对象。每个属性的值可以是 null,也可以是一个验证函数。验证函数将接收传递给 $emit 调用的额外参数。例如,如果 this.$emit("foo", 1, 2) 被调用,foo 的相应验证函数将接收参数 1 和 2。验证函数应该返回一个布尔值来表示事件参数是否有效。
{emits: {// no validationclick: null,// with validation//submit: payload => {if (payload.email && payload.password) {return true} else {console.warn(`Invalid submit event payload!`)return false}}}}
fallthrough 控制
在 #154 中提出的新的属性 fallthrough 行为现在适用于组件上使用 v-on 监听器的自动 fallthrough:
<Foo @click="onClick" />
为了向后兼容,我们没有要求 emits 通过组件抛出的事件来触发 click。因此在上面的例子中,如果没有 emits 选项,监听器可以被 Foo 的根元素的原生 click 事件或 Foo 发出的自定义事件所触发。
然而,如果通过使用 emits 选项将 click 声明为一个自定义事件,那么它将只被自定义事件触发,而不再作为一个原生监听器 fallthrough。
由 emits 声明的事件监听器也被排除在组件的 this.$attrs 之外。
类型推导
对象验证器的语法是在考虑 TypeScript 类型推导的情况下选择的。验证器的类型签名可以用于类型 $emit 调用。
const Foo = defineComponent({emits: {submit: (payload: { email: string; password: string }) => {// perform runtime validation}},methods: {onSubmit() {this.$emit('submit', {email: 'foo@bar.com',password: 123 // Type error!})this.$emit('non-declared-event') // Type error!}}})
缺点
- 该选项需要对所有发出的自定义事件的组件付出一些额外的精力。然而,它在技术上是可选的,其好处应该超过所需要的额外精力。
- 运行时验证应该只在开发模式下进行,但有可能会使得生产环境的包的大小增加。Props 验证器也有同样的问题。这两个问题都可以通过一个 Babel 插件来解决,该插件可以在生产构建中把
props和emits转换为 Array 格式。这样一来,只有开发模式的代码被剥离,但运行时的行为将保持一致。
备选方案
N/A
采纳策略
emits 选项的引入不应该破坏 $emit 的任何现有用法。
然而,随着 fallthrough 行为的改变,最理想的做法是始终声明抛出的事件。我们可以:
- 提供一个 codemod,自动扫描组件中所有
$emit调用的实例并生成emits选项。 - (Opt-in)当一个抛出的事件没有使用选项声明时,抛出一个运行时警告。
没有解决的问题
N/A
