当前位置: 首页 > news >正文

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

<!-- 父组件 -->
<ChildComponent 
  :applyBasicInfo="任何类型的数据" <!-- 可以是对象、字符串、数字等 -->
  operateCommandType="任何内容"    <!-- 可以是任意类型 -->
/>

<!-- 子组件 -->
<script setup>
// 使用时需要自行确保类型正确
console.log(props.applyBasicInfo) // 可能是任意类型
</script>

🆚 与其他声明方式的对比

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

⚠️ 潜在风险示例

vue

<!-- 父组件传递错误类型 -->
<ChildComponent 
  :applyBasicInfo="123"        <!-- 传递数字 -->
  operateCommandType           <!-- 未传递 -->
/>

<!-- 子组件使用时 -->
<script setup>
// 可能引发运行时错误
props.applyBasicInfo.name      // 报错:数字没有 name 属性
props.operateCommandType       // 拼写错误也不会警告(正确是 operateCommandType)
</script>

💡 为什么要用这种写法?

  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<ApplyBasicInfo>, // 使用标准的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<ApplyBasicInfo>, // 类型断言
  required: true
}
  • Object:Vue 的运行时类型校验(基础对象类型)

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

  • 双重效果

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

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

3. 对比普通对象声明

typescript

// 普通写法(只有 Vue 校验)
applyBasicInfo: {
  type: Object,  // 只知道是个对象,不清楚具体结构
  required: true
}

// 当前写法(Vue校验 + TS类型)
applyBasicInfo: {
  type: Object as PropType<ApplyBasicInfo>, // 明确对象结构
  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

<template>
  <!-- 显示申请人信息 -->
  <div>{{ props.applyBasicInfo.applicant }}</div>
  
  <!-- 根据操作类型显示不同内容 -->
  <div v-if="operateCommandType === 'info-view'">
    查看模式
  </div>
</template>

⚠️ 常见错误及解决方案

错误1:未定义接口

typescript

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

vue

<!-- 父组件传递错误数据结构 -->
<MyComponent :apply-basic-info="{ id: '100' }" />
<!-- 错误:id 应该是 number -->
错误3:缺少必要属性

typescript

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

🆚 不同技术栈的写法对比

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

📌 最佳实践建议

  1. 接口定义规范

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

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

      typescript

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

    typescript

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

    typescript

    // 对于复杂对象,建议提供默认值函数
    applyBasicInfo: {
      type: Object as PropType<ApplyBasicInfo>,
      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

    // 父组件使用时
    <MyComponent 
      :apply-basic-info="{
        id: 123,           // ✅ 必须 number
        name: '张三',       // ✅ 必须 string
        status: 'pending',  // ✅ 必须是枚举值
        createTime: new Date() // ✅ 必须 Date
      }"
    />

⚠️ 常见错误示例

typescript

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

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

// 错误3:错误的值类型
<MyComponent :apply-basic-info="'字符串'" /> 
// ❌ Vue 控制台警告:期望 Object,得到 String

🛠️ 在组件中的使用

vue

<script setup>
// 获得智能提示
const submit = () => {
  console.log(props.applyBasicInfo.id) // 正确:number 类型
  console.log(props.operateCommandType.toUpperCase()) // 正确:string 方法
}

// 类型安全操作
const statusLabel = computed(() => {
  switch(props.applyBasicInfo.status) {
    case 'pending': return '审批中';
    case 'approved': return '已通过';
    // case 'rejected' 会触发 TS 错误(如果接口中未定义)
  }
})
</script>

📌 最佳实践建议

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

// 需要单独定义默认值
const { operateCommandType = "info-view" } = toRefs(props);

这段代码是 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

    // 父组件使用
    <ChildComponent 
      :applyBasicInfo="myApplyInfo" 
      operateCommandType="edit"
    />
    
    // 子组件内使用
    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 的语法

http://www.dtcms.com/a/122795.html

相关文章:

  • Python 实现的运筹优化系统数学建模详解(0-1规划背包问题)
  • PHP:从诞生到未来的Web开发利器
  • 数据结构和大数据处理及其加密算法
  • SMB 协议
  • uniApp 设置动态tabs(不是自定义tab哈)
  • 在执行生信分析的时候提示缺少一些R包的报错解决
  • WebForms ViewState
  • SnowNLP 使用大全
  • Scala Iterator(迭代器)
  • 算法进阶指南 袭击
  • 蓝桥杯 跑步计划(模拟日期)
  • JMeter从入门到荒废-常见问题汇总
  • go游戏后端开发30:弃牌逻辑与后续操作
  • vue3中左右布局两个个组件使用vuedraggable实现左向右拖动,右组件列表可上下拖动
  • rook-ceph xx/xxx objects misplaced (xx%)
  • 基于大模型应用技能的学习路径
  • NO.80十六届蓝桥杯备战|数据结构-字符串哈希|兔子与兔子(C++)
  • CCRC 与 EMVCo 双认证:中国智能卡企业的全球化突围
  • git 总结遇到的问题
  • B+树与红黑树
  • 第三章:SQL 高级功能与性能优化
  • CentOS 中下载rpm包并安装
  • PhpStorm配置函数和文件注释模板
  • Python设计模式:工厂模式
  • 凯斯西储大学CWRU数据集变体
  • python中的数据模型-pydantic浅讲
  • 02_SQL分库分表及Java实现
  • 【重构谷粒商城12】npm快速入门
  • Python第八章:数据可视化——Json数据
  • Android 开发中compileSdkVersion 和 targetSdkVersion