Skip to content
目录

Props 和 Emits

下面来看看如何给 Props 和 Emits 做类型声明。

Props

script setup 中,可以使用 defineProps API,使 Props 获得完整的类型推断。

Props 声明

  1. 通过泛型参数定义 props 类型:类型声明
<script setup lang="ts">
const props = defineProps<{
  name: string
  phone: number
  age?: number
  visible: boolean
  school: string[]
}>()
</script>
1
2
3
4
5
6
7
8
9
  1. 通过 interfacetype

借助 interface 和 type,我们抽离了 props 的类型,让代码更简洁。

  1. 从参数中推导类型:运行时声明
<script setup lang="ts">
const props = defineProps({
  name: { type: String, required: true }
  phone: Number
  age: Number
  visible: Boolean
  school: {
    type: Array,
    default () {
      return []
    }
  }
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这和 vue2 中的定义 props 类似。

Props 默认值

基于类型的声明的缺陷是无法给 props 设置默认值。

我们可以借助响应式语法糖withDefaults 来实现给 props 设置默认值

  1. 响应式语法糖

响应式语法糖目前还在实验阶段,需要在配置中显式开启

// vite.config.js
export default {
  plugins: [
    vue({
      reactivityTransform: true
    })
  ]
}
1
2
3
4
5
6
7
8

开启后我们就可以给 props 设置默认值了。

<script setup lang="ts">
interface Props {
  foo: string
  visible: boolean
  bar?: number
  labels: string[]
}

// 对 defineProps() 的响应性解构
// 默认值会被编译为等价的运行时选项
const { 
  foo = 'hello',  
  visible = false, 
  bar = 100, 
  labels = ['one', 'two']
} = defineProps<Props>()
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  1. withDefaults

withDefaults 是一个编译器宏。

<script setup lang="ts">
interface Props {
  foo: string
  visible: boolean
  bar?: number
  labels?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  foo: 'hello',
  visible: false,
  bar: 100
  labels: () => ['one', 'two']
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

withDefaults 在编译时,会将以上代码编译为等价的运行时声明 props

<script setup lang="ts">
const props = defineProps({
  msg: { type: String, default: 'hello' }
  labels: {
    type: Array,
    default () {
      return ['one', 'two']
    }
  }
})
</script>
1
2
3
4
5
6
7
8
9
10
11

事件

为了让事件获得完整的类型推断,我们需要使用 defineEmits API。

  1. 类型声明
<script setup lang="ts">
const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
</script>
1
2
3
4
5
6

在上面的代码中,我们声明了 changeupdate,两个事件,idvalue 分别为两个事件的参数。

  1. 运行时声明
<script setup lang="ts">
const emit = defineEmits(['change', 'update'])
</script>
1
2
3

如果不使用 script setup 的写法,则是:

<script>
import { defineComponent } from 'vue'

export default defineComponent({
  emits: ['change'],
  setup(props, { emit }) {
    emit('change') // <-- 类型检查 / 自动补全
  }
})
</script>
1
2
3
4
5
6
7
8
9
10

推荐使用类型声明的方式来声明事件,能直接让我们控制事件的参数和返回值的类型。

Props 和 Emits has loaded