三门峡市网站建设_网站建设公司_SEO优化_seo优化
2026/1/14 21:24:35 网站建设 项目流程

Vue 3 提供了两种 props 声明方式:泛型类型声明和运行时选项声明。


泛型类型声明(defineProps<{prop:Type}>())在编译时进行类型检查,完全支持 TypeScript,适合新项目和追求类型安全的场景。


运行时选项声明(defineProps({prop:{type:...}}))支持运行时验证、默认值和自定义验证器,但需要 PropType 辅助类型。


两种语法不能混用。


推荐优先使用泛型类型声明以获得更好的开发体验和类型安全,仅在需要运行时特性时使用选项声明。


实际应用中需根据项目需求选择合适的声明方式。


泛型类型声明 vs 运行时选项声明语法对比

特性泛型类型声明运行时选项声明
语法defineProps<{ prop: Type }>()defineProps({ prop: { type: ..., required: ... } })
TypeScript支持✅ 完全支持类型推断✅ 需要结合PropType辅助类型
Vue版本要求Vue 3.3+ (推荐)Vue 3.0+
类型检查时机编译时(开发阶段)运行时(实际执行时)
代码示例typescript<br>defineProps<{<br> list: ColumnProps[]<br>}>()typescript<br>defineProps({<br> list: {<br> type: Array as PropType<ColumnProps[]>,<br> required: true<br> }<br>})
默认值设置需配合withDefaults()直接在选项中设置default
必填/可选控制通过?修饰符
list?: Type(可选)
list: Type(必填)
通过required选项
类型导入直接使用TypeScript类型需要导入PropType
验证函数不支持支持validator选项
复杂类型直接使用TypeScript类型需要PropType包装
IDE智能提示✅ 优秀✅ 良好
与Composition API集成✅ 无缝✅ 良好
编译产物大小较小(无运行时类型检查代码)较大(包含运行时检查)
推荐场景1. 新项目开发
2. 纯TypeScript项目
3. 追求最佳类型安全
1. 需要运行时验证
2. 需要默认值
3. 需要自定义验证器
混合使用❌ 不能与运行时选项混用✅ 可与泛型类型配合withDefaults()

实际应用建议:

使用泛型类型声明(现代推荐)

// 简洁、类型安全 const props = defineProps<{ list: ColumnProps[] // 必填 title?: string // 可选 }>(); // 有默认值时 const props = withDefaults(defineProps<{ list: ColumnProps[] size?: 'small' | 'medium' | 'large' }>(), { size: 'medium' });

使用运行时选项(需要运行时特性)

import type { PropType } from 'vue'; const props = defineProps({ list: { type: Array as PropType<ColumnProps[]>, required: true, default: () => [], validator: (value) => value.length <= 10 // 额外验证 } });

选择原则

  • 新项目优先使用泛型类型声明

  • 需要validator或复杂运行时逻辑时使用运行时选项

  • 避免两种语法混用在同一defineProps调用中


代码分析:易错点


<script setup lang='ts'> import { computed, type PropType } from 'vue'; //“PropType”是一种类型,必须在启用 "verbatimModuleSyntax" 时使用仅类型导入进行导入。 //这个错误是因为 TypeScript 配置中的 verbatimModuleSyntax 选项要求对类型和值导入进行区分。当你使用 PropType 时,它是一个类型,需要按照特定的方式导入。 //使用 type PropType:在导入时添加 type 关键字,表明这是一个类型导入 //使用 withDefaults:为了处理可选属性的默认值问题 //定义专栏属性的接口 interface ColumnProps { id: number; title: string; avatar?: string;// 可选属性 description: string; } //错误写法1 // const props = defineProps<{ // list:{ // type: Array<ColumnProps>, // required: true, // } // }>(); //错误写法2 // const props = defineProps<{ // list:{ // type: PropType<ColumnProps[]>, // required: true, // } // }>(); //正确写法 const props = defineProps<{ list:Array<ColumnProps>; }>(); //处理数据,如果没有头像,使用默认头像 //使用computed属性处理数据 import defaultAvatar from '@/assets/default-avatar.png' // 静态导入 const columnList = computed(() => { return props.list.map(column => { if (!column.avatar) { // 使用 require 方法引入本地图片 //ReferenceError: require is not defined at ColumnList.vue //这个问题是因为在 Vue 3 + Vite 环境中使用了 require 函数,而 Vite 默认不支持 CommonJS 的 require 语法。需要修改 ColumnList.vue 中的相关代码。 //column.avatar = require('@/assets/default-avatar.png'); column.avatar = defaultAvatar; } return column; }); }); // 导出 ColumnProps 类型以供外部使用 export type { ColumnProps }; </script>

主要问题

类型声明语法混合错误:在<script setup>中使用defineProps时,不能混用类型声明和运行时选项


三种写法的正确形式:

正确写法1:纯类型声明(使用泛型)

// ✅ 正确 - 纯类型声明 const props = defineProps<{ list: ColumnProps[] }>();

正确写法2:运行时声明(使用对象语法)

// ✅ 正确 - 运行时声明 import type { PropType } from 'vue'; const props = defineProps({ list: { type: Array as PropType<ColumnProps[]>, required: true } });

正确写法3:混合声明(Vue 3.3+)

// ✅ 正确 - 混合声明(TypeScript + 运行时选项) import type { PropType } from 'vue'; const props = withDefaults(defineProps<{ list: ColumnProps[] }>(), { // 这里可以设置默认值 // list: () => [] }); // 或者如果需要 required,直接在类型中标注 const props = defineProps<{ list: ColumnProps[] // 默认是必填的 }>();

建议的优化写法:

根据你的需求,如果要确保list是必填的,推荐使用:

// 方案1:简洁的纯类型声明(推荐) const props = defineProps<{ list: ColumnProps[] // TypeScript中默认可选,但这里表示需要传入 }>(); // 方案2:如果需要明确的运行时验证 import type { PropType } from 'vue'; const props = defineProps({ list: { type: Array as PropType<ColumnProps[]>, required: true, default: () => [] // 如果需要默认值 } });

关键点:在<script setup>中,不能同时使用泛型类型声明和运行时选项声明语法,需要选择其中一种方式。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询