|
这里或许是互联网从业者的最后一片净土,随客社区期待您的加入!
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 zzz 于 2025-9-28 17:09 编辑
在 Vue 3 中,我们可以使用 TypeScript 为组件的 props 和 emits 提供类型声明。
1.Props的类型声明 选项式API - import { defineComponent, PropType } from 'vue'
- interface User {
- id: number
- name: string
- email: string
- }
- export default defineComponent({
- props: {
- // 基础类型
- title: String,
- count: {
- type: Number,
- required: true
- },
-
- // 对象类型
- user: {
- type: Object as PropType<User>,
- required: true
- },
-
- // 数组类型
- tags: {
- type: Array as PropType<string[]>,
- default: () => []
- },
-
- // 联合类型
- status: {
- type: String as PropType<'pending' | 'success' | 'error'>,
- default: 'pending'
- },
-
- // 函数类型
- onSubmit: {
- type: Function as PropType<(data: any) => Promise<void>>,
- required: false
- }
- }
- })
复制代码 组合式API < script setup > - <script setup lang="ts">
- // 方式1: 使用接口
- interface User {
- id: number
- name: string
- email: string
- }
- interface Props {
- title?: string
- count: number
- user: User
- tags?: string[]
- status?: 'pending' | 'success' | 'error'
- onSubmit?: (data: any) => Promise<void>
- }
- const props = defineProps<Props>()
- // 方式2: 内联类型声明
- const props = defineProps<{
- title?: string
- count: number
- user: User
- tags?: string[]
- status?: 'pending' | 'success' | 'error'
- onSubmit?: (data: any) => Promise<void>
- }>()
- // 方式3: 运行时声明 + 类型(支持默认值)
- const props = withDefaults(defineProps<{
- title?: string
- count: number
- user: User
- tags?: string[]
- status?: 'pending' | 'success' | 'error'
- }>(), {
- title: '默认标题',
- tags: () => ['vue', 'typescript'],
- status: 'pending'
- })
- </script>
复制代码2. Emits 的类型声明 选项式API - import { defineComponent } from 'vue'
- export default defineComponent({
- emits: {
- // 无参数事件
- 'click': null,
-
- // 带参数事件(运行时验证)
- 'update:modelValue': (value: string) => typeof value === 'string',
-
- // 复杂参数事件
- 'submit': (payload: { email: string; password: string }) => {
- return payload.email !== undefined && payload.password !== undefined
- }
- }
- })
复制代码 组合式API < script setup > - <script setup lang="ts">
- // 方式1: 类型字面量(推荐)
- const emit = defineEmits<{
- (e: 'click'): void
- (e: 'update:modelValue', value: string): void
- (e: 'submit', payload: { email: string; password: string }): void
- (e: 'error', message: string, code?: number): void
- }>()
- // 方式2: 更简洁的语法(Vue 3.3+)
- const emit = defineEmits<{
- click: []
- 'update:modelValue': [value: string]
- submit: [payload: { email: string; password: string }]
- error: [message: string, code?: number]
- }>()
- // 使用示例
- const handleClick = () => {
- emit('click')
- }
- const handleInput = (value: string) => {
- emit('update:modelValue', value)
- }
- const handleSubmit = () => {
- emit('submit', { email: 'test@example.com', password: '123456' })
- }
- const handleError = () => {
- emit('error', 'Something went wrong', 500)
- }
- </script>
复制代码3.完整的组件示例 - <script setup lang="ts">
- // 类型定义
- interface User {
- id: number
- name: string
- email: string
- avatar?: string
- }
- interface FormData {
- title: string
- content: string
- tags: string[]
- }
- // Props 类型
- interface Props {
- user: User
- initialData?: FormData
- loading?: boolean
- disabled?: boolean
- maxLength?: number
- }
- const props = withDefaults(defineProps<Props>(), {
- loading: false,
- disabled: false,
- maxLength: 1000
- })
- // Emits 类型
- const emit = defineEmits<{
- (e: 'submit', data: FormData): void
- (e: 'cancel'): void
- (e: 'update:user', user: Partial<User>): void
- (e: 'error', message: string): void
- }>()
- // 组件逻辑
- const formData = reactive<FormData>({
- title: props.initialData?.title || '',
- content: props.initialData?.content || '',
- tags: props.initialData?.tags || []
- })
- const handleSubmit = () => {
- if (formData.title.trim() === '') {
- emit('error', '标题不能为空')
- return
- }
-
- emit('submit', { ...formData })
- }
- const handleUserUpdate = (updates: Partial<User>) => {
- emit('update:user', updates)
- }
- </script>
- <template>
- <form @submit.prevent="handleSubmit" class="user-form">
- <div class="form-group">
- <label>标题</label>
- <input
- v-model="formData.title"
- :disabled="props.disabled || props.loading"
- :maxlength="props.maxLength"
- />
- </div>
-
- <div class="form-group">
- <label>内容</label>
- <textarea
- v-model="formData.content"
- :disabled="props.disabled || props.loading"
- />
- </div>
-
- <div class="actions">
- <button
- type="button"
- @click="$emit('cancel')"
- :disabled="props.loading"
- >
- 取消
- </button>
- <button
- type="submit"
- :disabled="props.disabled || props.loading"
- >
- {{ props.loading ? '提交中...' : '提交' }}
- </button>
- </div>
- </form>
- </template>
复制代码
|
|