vue3中defineProps的使用说明

1、数组写法

const props = defineProps(["applyBasicInfo", "operateCommandType"]);

 这是一个非常基础的 Vue props 声明方式,适用于简单场景。以下是详细解释:


 代码含义

javascript

const props = defineProps(["applyBasicInfo", "operateCommandType"]);
  • 作用:声明组件接收两个 props(属性)

  • 特点:仅指定 prop 名称,不进行任何类型校验

  • 等价于

    javascript

    defineProps({
      applyBasicInfo: null,       // 无类型检查
      operateCommandType: null     // 无类型检查
    })

 关键特性分析

1. 极简声明
  • 只声明 props 的名称(字符串数组)

  • 不校验类型

  • 没有默认值

  • 不强制 required

2. 适用场景
  • 快速原型开发

  • 不需要类型检查的简单组件

  • 临时过渡代码

3. 实际效果

vue



  operateCommandType="任何内容"    
/>



 与其他声明方式的对比

特性 数组写法 对象写法(完整) TypeScript 类型写法
类型校验 ❌ 无 ✅ Vue 运行时校验 ✅ 编译时校验
默认值 ❌ 不能设置 ✅ 通过 default 设置 ✅ 通过 withDefaults 设置
必需性控制 ❌ 默认都是可选 ✅ 通过 required 控制 ✅ 通过 ? 符号控制
类型提示 ❌ 无 基础类型提示 ✅ 完整类型提示
代码安全性 低(可能运行时出错) 中(有基础校验) 高(编译时拦截错误)

⚠️ 潜在风险示例

vue



  operateCommandType           
/>



 为什么要用这种写法?

  1. 历史兼容:Vue 2 的 props 数组写法在 Vue 3 中仍然可用

  2. 快速开发:节省写类型校验的时间

  3. 简单场景:当 props 类型不重要或可以确定时


️ 如何改进?

基础改进(添加类型校验):

javascript

const props = defineProps({
  applyBasicInfo: {
    type: Object,
    required: true
  },
  operateCommandType: {
    type: String,
    default: "view"
  }
});
高级改进(TypeScript):

typescript

interface ApplyBasicInfo {
  id: number;
  name: string;
}

const props = defineProps<{
  applyBasicInfo: ApplyBasicInfo;
  operateCommandType?: string;
}>();

 最佳实践建议

  1. 仅用于临时代码:正式项目建议使用完整声明

  2. 配合 JSDoc 使用(如果不用 TypeScript):

    javascript

    /**
     * @typedef {Object} ApplyBasicInfo
     * @property {number} id
     * @property {string} name
     */
    
    const props = defineProps(["applyBasicInfo", "operateCommandType"]);
  3. 渐进式增强:后续逐步替换为完整声明


这种写法就像骑自行车不戴头盔——简单快捷,但不够安全。建议新手仅在快速验证想法时使用,正式开发中尽量使用更完善的 props 声明方式。

2、 对象写法(纯 JavaScript 项目的写法,运行时 props 声明

const props = defineProps({
  applyBasicInfo: {
    type: Object, // 要求必须是 Object 类型
    required: true // 表示父组件必须传递这个prop,不能与 default 同时使用
  },
  operateCommandType: {
    type: String, // 要求必须是 String 类型
    default: "info-view" // 表示当父组件没有传递时使用默认值,不能与 required 同时使用
  }
});
数组简写 vs 对象写法

javascript

复制

// 简写方式(不推荐)
defineProps(['applyBasicInfo', 'operateCommandType'])

// vs 

// 当前对象写法(推荐)
defineProps({
  applyBasicInfo: { type: Object, required: true },
  operateCommandType: { type: String, default: "info-view" }
})
特性 数组写法 对象写法
类型检查 ❌ 无 ✅ 基础类型检查
默认值 ❌ 不可设置 ✅ 可设置
必填控制 ❌ 默认全部可选 ✅ 精确控制
代码安全性 中等

这段代码使用 Vue 的 defineProps 方法声明组件需要接收的两个 props(组件参数),并设置了参数的基本验证规则。 

3、 TypeScript 的类型声明写法

3.1、使用标准的PropType进行对象类型定义

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 同时使用
  }
});

关键概念拆解

1. 类型导入部分

typescript

import type { PropType } from "vue";
import type { ApplyBasicInfo } from "@/interface";
  • PropType:Vue 提供的类型工具,用于在运行时声明中指定复杂类型

  • ApplyBasicInfo:自定义的业务数据类型(通常定义在 src/interface.ts 等位置)

  • import type:TypeScript 语法,表示只导入类型信息,不导入实际代码

2. 核心 props 声明

typescript

applyBasicInfo: {
  type: Object as PropType, // 类型断言
  required: true
}
  • Object:Vue 的运行时类型校验(基础对象类型)

  • as PropType:类型断言,告诉 TypeScript 这个对象的具体结构

  • 双重效果

    • 运行时:Vue 检查传入的是否为对象

    • 开发时:TypeScript 检查对象是否符合 ApplyBasicInfo 的结构

3. 对比普通对象声明

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


⚠️ 常见错误及解决方案

错误1:未定义接口

typescript

// 错误提示:Cannot find name 'ApplyBasicInfo'
// 解决方案:确保类型文件正确定义并导出
// 在 @/interface.ts 中:
export interface ApplyBasicInfo { ... }
错误2:错误类型传递

vue



错误3:缺少必要属性

typescript

// 组件内使用时
const submit = () => {
  console.log(props.applyBasicInfo.createTime) // 如果接口中有该属性
}
// 当父组件传递的对象缺少 createTime 时,TS 会报错

不同技术栈的写法对比

场景 JavaScript 写法 TypeScript 基础写法 当前进阶写法
props 类型 type: Object type: Object Object as PropType
代码提示 显示 Object 类型 显示具体接口属性
类型安全
维护成本 高(需口头沟通数据结构) 中(需查看接口定义) 低(直接提示数据结构)

最佳实践建议

  1. 接口定义规范

    • 在 src/types 或 src/interface 目录统一管理类型

    • 为每个接口添加文档注释

      typescript

      interface ApplyBasicInfo {
        /**
         * 申请的唯一标识
         * @example 123456
         */
        id: number;
      }
  2. props 校验增强

    typescript

    applyBasicInfo: {
      type: Object as PropType,
      required: true,
      validator: (value: ApplyBasicInfo) => {
        return !!value.id // 添加自定义校验逻辑
      }
    }
  3. 默认值处理技巧

    typescript

    // 对于复杂对象,建议提供默认值函数
    applyBasicInfo: {
      type: Object as PropType,
      default: () => ({ id: 0, applicant: '', status: 'pending' })
    }

这种写法是 Vue 3 项目中平衡类型安全和开发效率的典型实践,既能享受 TypeScript 的类型提示优势,又保留了 Vue 原有的 props 校验机制,特别适合中大型项目维护使用。

3.2、混合写法(结合了 Vue 的运行时 props 校验和 TypeScript 类型提示的混合写法)

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"
  }
});

 关键部分详解

1. 类型导入

typescript

import type { ApplyBasicInfo } from "@/interface";
  • 作用:导入自定义类型(通常定义在 src/interface.ts 或类型声明文件中)

  • 示例类型定义

    typescript

    // 假设在 @/interface 中
    interface ApplyBasicInfo {
      id: number;
      name: string;
      status: 'pending' | 'approved';
      createTime: Date;
    }
2. defineProps 函数

typescript

const props = defineProps({...});
  • Vue 3 特有语法:用于声明组件接收的 props

  • 返回响应式对象:包含所有已声明的 props

3. applyBasicInfo 属性

typescript

{
  type: Object as () => ApplyBasicInfo,
  required: true
}
  • 运行时类型Object 表示接受对象类型(Vue 的运行时校验)

  • 类型断言as () => ApplyBasicInfo 为 TypeScript 提供类型提示

  • 实际效果

    typescript

    // 使用时可以获得类型提示
    props.applyBasicInfo.id // 提示 number 类型
    props.applyBasicInfo.name // 提示 string 类型
4. operateCommandType 属性

typescript

{
  type: String,
  default: "info-view"
}
  • 标准 Vue 校验:接受字符串类型

  • 默认值:当父组件未传递时默认为 "info-view"


 代码特点

特性 说明
双重校验 Vue 运行时类型检查 + TypeScript 静态类型提示
明确契约 通过 ApplyBasicInfo 接口明确定义数据结构
渐进式类型 不需要完全迁移到 TypeScript 也能获得部分类型优势
代码可维护性 接口修改只需改动一处定义

 不同写法的对比

这种写法 纯 TypeScript 写法 纯 JavaScript 写法
类型提示 ✅ 完整类型提示 ✅ 完整类型提示 ❌ 无
运行时校验 ✅ Vue 会校验 Object 类型 ❌ 需额外配置 ✅ 标准校验
默认值支持 ✅ 直接通过 default 设置 ❌ 需要使用 withDefaults ✅ 原生支持
代码复杂度 中等 简洁(类型优先) 高(需自行维护类型约束)

 为什么这样写?

  1. 平衡开发体验

    • 获得 TypeScript 的智能提示

    • 保留 Vue 的运行时校验安全网

  2. 渐进增强

    • 适合逐步将 JavaScript 项目迁移到 TypeScript

    • 不需要一次性重写所有类型

  3. 明确数据契约

    typescript

    // 父组件使用时
    

⚠️ 常见错误示例

typescript

// 错误1:缺少必填字段
props.applyBasicInfo.missingProp // ❌ TS 报错:属性不存在

// 错误2:类型不匹配
props.applyBasicInfo.id = "100" // ❌ TS 报错:不能将 string 赋给 number

// 错误3:错误的值类型
 
// ❌ Vue 控制台警告:期望 Object,得到 String

️ 在组件中的使用

vue


 最佳实践建议

  1. 保持接口同步:当 ApplyBasicInfo 类型修改时,需要同步更新所有使用它的组件

  2. 默认值处理:对于复杂对象 prop,建议:

    typescript

    // 使用解构默认值
    const { applyBasicInfo = DEFAULT_INFO } = toRefs(props)
  3. 文档注释:在接口定义处添加详细注释

    typescript

    interface ApplyBasicInfo {
      /** 申请ID,唯一标识 */
      id: number;
      /** 申请人姓名 */
      name: string;
      // ...
    }

这种写法特别适合需要逐步引入 TypeScript 的 Vue 项目,既能享受类型系统的优势,又不会完全颠覆原有的开发模式。

3.3、与3.1等效的TypeScript 的类型声明写法

import { toRefs } from "vue";
import type { ApplyBasicInfo } from "@/interface";

const props = defineProps<{
  applyBasicInfo: ApplyBasicInfo;
  operateCommandType: string;
}>();

这段代码是 Vue 3 组合式 API 中使用 TypeScript 的类型声明写法,主要用于定义组件的 props。让我们分步详细解释:

  1. defineProps 的作用

    • 这是 Vue 3 的组合式 API 函数,用于声明组件接收的 props

    • 类似于选项式 API 中的 props 选项,但更符合组合式 API 的编程风格

  2. 泛型参数 <...>

    • 这是 TypeScript 的泛型语法,用于为 defineProps 提供类型注解

    • 泛型参数中定义了一个对象类型,描述了这个组件接收的所有 props 及其类型

  3. 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" 等字符串枚举值

  4. 最终结果

    • 定义了一个名为 props 的常量

    • 该常量包含两个响应式属性:

    javascript

    {
      applyBasicInfo: { /* 具体数据 */ },
      operateCommandType: "edit" // 示例值
    }
  5. 在组件中的使用

    vue

    // 父组件使用
    
    
    // 子组件内使用
    console.log(props.applyBasicInfo.applicantName)
    console.log(props.operateCommandType)
  6. 类型检查

    • 如果父组件传递错误类型的 prop,TypeScript 会给出编译时错误

    • 例如:传递数字类型的 operateCommandType 会报错

  7. 对比 JavaScript 版本
    如果是纯 JavaScript,等效写法可能是:

    javascript

    const props = defineProps({
      applyBasicInfo: {
        type: Object,
        required: true
      },
      operateCommandType: {
        type: String,
        default: 'view'
      }
    })

注意事项

  1. 需要确保 ApplyBasicInfo 类型已经在项目中定义(通常是在独立的类型声明文件中)

  2. 这种写法需要 Vue 3.3+ 版本支持

  3. 如果不需要 TypeScript 类型检查,可以使用运行时声明方式

  4. 这种写法默认 props 都是 required 的,如果需要可选参数,应该使用 propName?: Type 的语法

实例代码:

在 Vue 3 的 


                    
                    

你可能感兴趣的:(前端,javascript,vue.js)