Vue 3 defineEmits 打破了 defineProps 类型

Posted

技术标签:

【中文标题】Vue 3 defineEmits 打破了 defineProps 类型【英文标题】:Vue 3 defineEmits breaks defineProps types 【发布时间】:2021-11-22 17:31:36 【问题描述】:

我正在使用 Vue 3 和 TS 4.4。我有一个用defineProps 定义其道具类型的组件。当我添加对defineEmits 的调用时,VS Code 开始告诉我我的props 变量在组件模板中不存在。这是源代码:

<script setup lang="ts">
import  defineProps, defineEmits, VueElement, defineComponent  from "vue";

const emit = defineEmits<
  "update:checked": boolean;
>();

const props = defineProps<
  label?: VueElement | string;
  checked?: boolean;
>();
</script>

<template>
  <label>
    <input
      type="checkbox"
      :checked="props.checked"
      @change="(event) => emit('update:checked', (event.target as any)?.checked)"
    />
     props.label 
  </label>
</template>

还有几个屏幕截图可以更好地展示我在 VS Code 中看到的内容。这是在添加defineEmits之后:

这是没有defineEmits

为 props 和 emits 定义类型的正确方法是什么?

【问题讨论】:

【参考方案1】:

defineEmits&lt;T&gt;() generic argument 本质上是一个 TypeScript 接口,它只定义了函数,它们接收特定的事件名称和可选参数:

interface Emits 
  (e: __EVENT1_NAME__ [, arg1: __ARG1_TYPE__ [, arg2: __ARG2_TYPE__]]...): void
  (e: __EVENT2_NAME__ [, arg1: __ARG1_TYPE__ [, arg2: __ARG2_TYPE__]]...): void

例子:

// as inline type
const emits = defineEmits<
  (eventName: 'hover', hovering: boolean): void
  (eventName: 'changed', newValue: number, id: string): void
>()
// as interface
interface Emits 
  (eventName: 'hover', hovering: boolean): void
  (eventName: 'changed', newValue: number, id: string): void

const emits = defineEmits<Emits>()
// as type alias
type Emits = 
  (eventName: 'hover', hovering: boolean): void
  (eventName: 'changed', newValue: number, id: string): void

const emits = defineEmits<Emits>()

对于您的update:checked 事件,代码应类似于以下内容:

// as inline type
const emits = defineEmits<
  (e: 'update:checked', checked: boolean): void
>()
// as interface
interface Emits 
  (e: 'update:checked', checked: boolean): void

const emits = defineEmits<Emits>()
// as type alias
type Emits = 
  (e: 'update:checked', checked: boolean): void

const emits = defineEmits<Emits>()

【讨论】:

不,您可以在同一个defineEmits() 调用中定义多个发射(如docs 所示)。如果在 VS Code 中使用 VueDX,请忽略模板中的错误(它似乎与 &lt;script setup&gt; 不完全兼容)。然而,模板中显示的ts 错误似乎是正确的。

以上是关于Vue 3 defineEmits 打破了 defineProps 类型的主要内容,如果未能解决你的问题,请参考以下文章

vue3-setup语法糖之组件传参(definePropsdefineEmitsdefineExpose)

如何打破我们的 def() 循环并进入下一个代码? [复制]

解决:使用 Vue 3 Script Setup 时 ESLint 报错 ‘defineProps‘ is not defined

Vue 组件道具上的数组类型打破了 Linter

Vue 打破了 DataTables 和 Pace JS

Vue Webpack 构建打破了 Bulma CSS