const props = defineProps(["applyBasicInfo", "operateCommandType"]);
这是一个非常基础的 Vue props 声明方式,适用于简单场景。以下是详细解释:
javascript
const props = defineProps(["applyBasicInfo", "operateCommandType"]);
作用:声明组件接收两个 props(属性)
特点:仅指定 prop 名称,不进行任何类型校验
等价于:
javascript
defineProps({ applyBasicInfo: null, // 无类型检查 operateCommandType: null // 无类型检查 })
只声明 props 的名称(字符串数组)
不校验类型
没有默认值
不强制 required
快速原型开发
不需要类型检查的简单组件
临时过渡代码
vue
operateCommandType="任何内容" />
特性 | 数组写法 | 对象写法(完整) | TypeScript 类型写法 |
---|---|---|---|
类型校验 | ❌ 无 | ✅ Vue 运行时校验 | ✅ 编译时校验 |
默认值 | ❌ 不能设置 | ✅ 通过 default 设置 | ✅ 通过 withDefaults 设置 |
必需性控制 | ❌ 默认都是可选 | ✅ 通过 required 控制 | ✅ 通过 ? 符号控制 |
类型提示 | ❌ 无 | 基础类型提示 | ✅ 完整类型提示 |
代码安全性 | 低(可能运行时出错) | 中(有基础校验) | 高(编译时拦截错误) |
vue
operateCommandType />
历史兼容:Vue 2 的 props 数组写法在 Vue 3 中仍然可用
快速开发:节省写类型校验的时间
简单场景:当 props 类型不重要或可以确定时
javascript
const props = defineProps({ applyBasicInfo: { type: Object, required: true }, operateCommandType: { type: String, default: "view" } });
typescript
interface ApplyBasicInfo { id: number; name: string; } const props = defineProps<{ applyBasicInfo: ApplyBasicInfo; operateCommandType?: string; }>();
仅用于临时代码:正式项目建议使用完整声明
配合 JSDoc 使用(如果不用 TypeScript):
javascript
/** * @typedef {Object} ApplyBasicInfo * @property {number} id * @property {string} name */ const props = defineProps(["applyBasicInfo", "operateCommandType"]);
渐进式增强:后续逐步替换为完整声明
这种写法就像骑自行车不戴头盔——简单快捷,但不够安全。建议新手仅在快速验证想法时使用,正式开发中尽量使用更完善的 props 声明方式。
const props = defineProps({
applyBasicInfo: {
type: Object, // 要求必须是 Object 类型
required: true // 表示父组件必须传递这个prop,不能与 default 同时使用
},
operateCommandType: {
type: String, // 要求必须是 String 类型
default: "info-view" // 表示当父组件没有传递时使用默认值,不能与 required 同时使用
}
});
javascript
复制
// 简写方式(不推荐) defineProps(['applyBasicInfo', 'operateCommandType']) // vs // 当前对象写法(推荐) defineProps({ applyBasicInfo: { type: Object, required: true }, operateCommandType: { type: String, default: "info-view" } })
特性 | 数组写法 | 对象写法 |
---|---|---|
类型检查 | ❌ 无 | ✅ 基础类型检查 |
默认值 | ❌ 不可设置 | ✅ 可设置 |
必填控制 | ❌ 默认全部可选 | ✅ 精确控制 |
代码安全性 | 低 | 中等 |
这段代码使用 Vue 的 defineProps
方法声明组件需要接收的两个 props(组件参数),并设置了参数的基本验证规则。
import type { PropType } from "vue";
import type { ApplyBasicInfo } from "@/interface";
const props = defineProps({
applyBasicInfo: {
type: Object as PropType, // 使用标准的PropType进行对象类型定义
required: true // 表示父组件必须传递这个prop,不能与 default 同时使用
},
operateCommandType: {
type: String,
default: "info-view" // 表示当父组件没有传递时使用默认值,不能与 required 同时使用
}
});
typescript
import type { PropType } from "vue"; import type { ApplyBasicInfo } from "@/interface";
PropType
:Vue 提供的类型工具,用于在运行时声明中指定复杂类型
ApplyBasicInfo
:自定义的业务数据类型(通常定义在 src/interface.ts
等位置)
import type
:TypeScript 语法,表示只导入类型信息,不导入实际代码
typescript
applyBasicInfo: { type: Object as PropType, // 类型断言 required: true }
Object
:Vue 的运行时类型校验(基础对象类型)
as PropType
:类型断言,告诉 TypeScript 这个对象的具体结构
双重效果:
运行时:Vue 检查传入的是否为对象
开发时:TypeScript 检查对象是否符合 ApplyBasicInfo
的结构
typescript
// 普通写法(只有 Vue 校验) applyBasicInfo: { type: Object, // 只知道是个对象,不清楚具体结构 required: true } // 当前写法(Vue校验 + TS类型) applyBasicInfo: { type: Object as PropType, // 明确对象结构 required: true }
mermaid
graph TD A[父组件传递 props] --> B{Vue 运行时校验} B -->|通过| C[组件内使用] B -->|不通过| D[控制台警告] C --> E[TypeScript 类型检查] E -->|类型正确| F[正常开发] E -->|类型错误| G[IDE 提示错误]
特性 | 普通 Object 类型 | 当前写法 |
---|---|---|
代码提示 | 只知道是对象,无具体属性提示 | ✅ 显示 ApplyBasicInfo 的所有属性 |
重构安全性 | 修改属性时不会报错 | ✅ 修改接口定义会引发相关代码报错 |
参数校验 | 只校验是否是对象 | ✅ 运行时对象校验 + 类型结构校验 |
协作效率 | 需要查文档看数据结构 | ✅ 直接通过提示查看数据结构 |
typescript
// 假设在 @/interface 中 interface ApplyBasicInfo { id: number; // 申请ID applicant: string; // 申请人姓名 status: 'pending' | 'approved'; // 申请状态 createTime: Date; // 创建时间 }
typescript
// 正确使用(有提示) props.applyBasicInfo.id // 提示 number 类型 props.applyBasicInfo.applicant // 提示 string 类型 // 错误使用(立即报错) props.applyBasicInfo.APPlicant // ❌ 拼写错误提示 props.applyBasicInfo.status = 'rejected' // ❌ 类型不匹配
vue
{{ props.applyBasicInfo.applicant }}查看模式
typescript
// 错误提示:Cannot find name 'ApplyBasicInfo' // 解决方案:确保类型文件正确定义并导出 // 在 @/interface.ts 中: export interface ApplyBasicInfo { ... }
vue
typescript
// 组件内使用时 const submit = () => { console.log(props.applyBasicInfo.createTime) // 如果接口中有该属性 } // 当父组件传递的对象缺少 createTime 时,TS 会报错
场景 | JavaScript 写法 | TypeScript 基础写法 | 当前进阶写法 |
---|---|---|---|
props 类型 | type: Object |
type: Object |
Object as PropType |
代码提示 | 无 | 显示 Object 类型 | 显示具体接口属性 |
类型安全 | 低 | 中 | 高 |
维护成本 | 高(需口头沟通数据结构) | 中(需查看接口定义) | 低(直接提示数据结构) |
接口定义规范:
在 src/types
或 src/interface
目录统一管理类型
为每个接口添加文档注释
typescript
interface ApplyBasicInfo { /** * 申请的唯一标识 * @example 123456 */ id: number; }
props 校验增强:
typescript
applyBasicInfo: { type: Object as PropType, required: true, validator: (value: ApplyBasicInfo) => { return !!value.id // 添加自定义校验逻辑 } }
默认值处理技巧:
typescript
// 对于复杂对象,建议提供默认值函数 applyBasicInfo: { type: Object as PropType, default: () => ({ id: 0, applicant: '', status: 'pending' }) }
这种写法是 Vue 3 项目中平衡类型安全和开发效率的典型实践,既能享受 TypeScript 的类型提示优势,又保留了 Vue 原有的 props 校验机制,特别适合中大型项目维护使用。
import type { ApplyBasicInfo } from "@/interface";
const props = defineProps({
applyBasicInfo: {
type: Object as () => ApplyBasicInfo, // 使用箭头函数返回类型
required: true // 表示父组件必须传递这个prop,不能与 default 同时使用
},
operateCommandType: {
type: String,
default: "info-view" // 表示当父组件没有传递时使用默认值,不能与 required 同时使用
}
});
这是一个结合了 Vue 的运行时 props 校验和 TypeScript 类型提示的混合写法代码,特别适用于 Vue 3 + TypeScript 项目。以下是逐层解析:
typescript
import type { ApplyBasicInfo } from "@/interface"; // 导入类型 const props = defineProps({ applyBasicInfo: { type: Object as () => ApplyBasicInfo, // 核心类型声明 required: true }, operateCommandType: { type: String, default: "info-view" } });
typescript
import type { ApplyBasicInfo } from "@/interface";
作用:导入自定义类型(通常定义在 src/interface.ts
或类型声明文件中)
示例类型定义:
typescript
// 假设在 @/interface 中 interface ApplyBasicInfo { id: number; name: string; status: 'pending' | 'approved'; createTime: Date; }
typescript
const props = defineProps({...});
Vue 3 特有语法:用于声明组件接收的 props
返回响应式对象:包含所有已声明的 props
typescript
{ type: Object as () => ApplyBasicInfo, required: true }
运行时类型:Object
表示接受对象类型(Vue 的运行时校验)
类型断言:as () => ApplyBasicInfo
为 TypeScript 提供类型提示
实际效果:
typescript
// 使用时可以获得类型提示 props.applyBasicInfo.id // 提示 number 类型 props.applyBasicInfo.name // 提示 string 类型
typescript
{ type: String, default: "info-view" }
标准 Vue 校验:接受字符串类型
默认值:当父组件未传递时默认为 "info-view"
特性 | 说明 |
---|---|
双重校验 | Vue 运行时类型检查 + TypeScript 静态类型提示 |
明确契约 | 通过 ApplyBasicInfo 接口明确定义数据结构 |
渐进式类型 | 不需要完全迁移到 TypeScript 也能获得部分类型优势 |
代码可维护性 | 接口修改只需改动一处定义 |
这种写法 | 纯 TypeScript 写法 | 纯 JavaScript 写法 | |
---|---|---|---|
类型提示 | ✅ 完整类型提示 | ✅ 完整类型提示 | ❌ 无 |
运行时校验 | ✅ Vue 会校验 Object 类型 | ❌ 需额外配置 | ✅ 标准校验 |
默认值支持 | ✅ 直接通过 default 设置 | ❌ 需要使用 withDefaults | ✅ 原生支持 |
代码复杂度 | 中等 | 简洁(类型优先) | 高(需自行维护类型约束) |
平衡开发体验:
获得 TypeScript 的智能提示
保留 Vue 的运行时校验安全网
渐进增强:
适合逐步将 JavaScript 项目迁移到 TypeScript
不需要一次性重写所有类型
明确数据契约:
typescript
// 父组件使用时
typescript
// 错误1:缺少必填字段 props.applyBasicInfo.missingProp // ❌ TS 报错:属性不存在 // 错误2:类型不匹配 props.applyBasicInfo.id = "100" // ❌ TS 报错:不能将 string 赋给 number // 错误3:错误的值类型// ❌ Vue 控制台警告:期望 Object,得到 String
vue
保持接口同步:当 ApplyBasicInfo
类型修改时,需要同步更新所有使用它的组件
默认值处理:对于复杂对象 prop,建议:
typescript
// 使用解构默认值 const { applyBasicInfo = DEFAULT_INFO } = toRefs(props)
文档注释:在接口定义处添加详细注释
typescript
interface ApplyBasicInfo { /** 申请ID,唯一标识 */ id: number; /** 申请人姓名 */ name: string; // ... }
这种写法特别适合需要逐步引入 TypeScript 的 Vue 项目,既能享受类型系统的优势,又不会完全颠覆原有的开发模式。
import { toRefs } from "vue";
import type { ApplyBasicInfo } from "@/interface";
const props = defineProps<{
applyBasicInfo: ApplyBasicInfo;
operateCommandType: string;
}>();
这段代码是 Vue 3 组合式 API 中使用 TypeScript 的类型声明写法,主要用于定义组件的 props。让我们分步详细解释:
defineProps 的作用:
这是 Vue 3 的组合式 API 函数,用于声明组件接收的 props
类似于选项式 API 中的 props
选项,但更符合组合式 API 的编程风格
泛型参数 <...>
:
这是 TypeScript 的泛型语法,用于为 defineProps 提供类型注解
泛型参数中定义了一个对象类型,描述了这个组件接收的所有 props 及其类型
props 具体定义:
typescript
{ applyBasicInfo: ApplyBasicInfo; operateCommandType: string; }
声明了组件需要接收两个 props:
a) applyBasicInfo:
类型为 ApplyBasicInfo
(这应该是一个自定义的 TypeScript 类型/接口)
可能是一个包含申请基本信息的对象,比如:
typescript
interface ApplyBasicInfo { id: number; applicantName: string; applyDate: Date; // ...其他字段 }
b) operateCommandType:
类型为 string
可能用于表示操作命令类型,比如:"create"、"edit"、"view" 等字符串枚举值
最终结果:
定义了一个名为 props
的常量
该常量包含两个响应式属性:
javascript
{ applyBasicInfo: { /* 具体数据 */ }, operateCommandType: "edit" // 示例值 }
在组件中的使用:
vue
// 父组件使用// 子组件内使用 console.log(props.applyBasicInfo.applicantName) console.log(props.operateCommandType)
类型检查:
如果父组件传递错误类型的 prop,TypeScript 会给出编译时错误
例如:传递数字类型的 operateCommandType 会报错
对比 JavaScript 版本:
如果是纯 JavaScript,等效写法可能是:
javascript
const props = defineProps({ applyBasicInfo: { type: Object, required: true }, operateCommandType: { type: String, default: 'view' } })
注意事项:
需要确保 ApplyBasicInfo
类型已经在项目中定义(通常是在独立的类型声明文件中)
这种写法需要 Vue 3.3+ 版本支持
如果不需要 TypeScript 类型检查,可以使用运行时声明方式
这种写法默认 props 都是 required 的,如果需要可选参数,应该使用 propName?: Type
的语法
在 Vue 3 的 语法中,当使用
withDefaults
为对象类型的 prop 设置默认值时,必须使用工厂函数返回默认对象(用箭头函数 () => {}
),这是 Vue 设计层面的强制要求,主要目的是避免多个组件实例共享同一个对象引用的问题。