外观风格
Props 和 Emits
下面来看看如何给 Props 和 Emits 做类型声明。
Props
在 script setup
中,可以使用 defineProps
API,使 Props 获得完整的类型推断。
Props 声明
- 通过泛型参数定义 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
2
3
4
5
6
7
8
9
- 通过
interface
或type
借助 interface 和 type,我们抽离了 props 的类型,让代码更简洁。
- 从参数中推导类型:运行时声明
<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
2
3
4
5
6
7
8
9
10
11
12
13
14
这和 vue2 中的定义 props 类似。
Props 默认值
基于类型的声明的缺陷是无法给 props 设置默认值。
我们可以借助响应式语法糖
和 withDefaults
来实现给 props 设置默认值
- 响应式语法糖
响应式语法糖目前还在实验阶段,需要在配置中显式开启
// vite.config.js
export default {
plugins: [
vue({
reactivityTransform: true
})
]
}
1
2
3
4
5
6
7
8
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 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
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
2
3
4
5
6
7
8
9
10
11
事件
为了让事件获得完整的类型推断,我们需要使用 defineEmits
API。
- 类型声明
<script setup lang="ts">
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
</script>
1
2
3
4
5
6
2
3
4
5
6
在上面的代码中,我们声明了 change
和 update
,两个事件,id
和 value
分别为两个事件的参数。
- 运行时声明
<script setup lang="ts">
const emit = defineEmits(['change', 'update'])
</script>
1
2
3
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
2
3
4
5
6
7
8
9
10
推荐使用类型声明的方式来声明事件,能直接让我们控制事件的参数和返回值的类型。