Vue3.5 企业级管理系统实战(六):Vue3中defineProps用法

上一节封装图标组件 SvgIcon 时,用到了 defineProps,因为它在开发中的重要性,这里简单看一下它的用法,已熟知用法的此节可跳过。

在 Vue3 的组件化开发体系里,组件间通信是构建高效、可维护应用程序的核心环节。defineProps 作为 Vue3 框架中专门用于接收父组件传递数据的关键函数,在整个组件通信机制中发挥着不可或缺的作用。它不仅极大地简化了组件间数据传递的流程,使其更加简洁高效,还严格遵循 Vue 框架倡导的单向数据流原则,确保了数据流动的清晰性和可预测性。可以说,defineProps 就像组件之间沟通的桥梁,让父组件能够将数据准确无误地传递给子组件,实现数据的 “按需分配”。

1 defineProps 基本用法解析

1.1 运行时声明方式

1.1.1 基本声明语法

在 Vue3 中,defineProps 最基础的使用方式是通过字符串数组来声明接收的属性。如下代码展示了一个简单组件如何接收 title 和 content 属性:

<template><div><h2>{{ props.title }}</h2><p>{{ props.content }}</p></div>
</template><script setup>
// 字符串数组形式声明
const props = defineProps(['title', 'content'])
</script>

这种方式简单直接,适用于快速搭建原型或对属性类型要求不高的场景。但它的局限性在于缺乏类型检查,在复杂项目中可能导致潜在的错误。

1.1.2 类型声明语法(推荐)

在不使用 TypeScript 类型注解时,我们可以利用 JavaScript 对象来声明 defineProps,并通过type 字段明确 props 的数据类型。这种方式在运行时进行类型检查,虽然不如 TypeScript 的静态类型检查严格,但对于简单项目或对强类型依赖不高的场景而言,十分便捷。

例如,创建一个展示文章基本信息的子组件:

<template><div><h2>{{ props.title }}</h2><p>{{ props.content }}</p></div>
</template><script setup>
const props = defineProps({title: {type: String,required: true},content: {type: String,default: '暂无内容摘要'}
})
</script>

在这段代码中,title 被声明为必需的字符串类型,content 同样是字符串类型并设置了默认值。当父组件传递数据时,若未提供 content,子组件会使用默认值展示。这种运行时声明方式符合 JavaScript 编程习惯,易于理解和维护。

1.2 基于类型的声明方式

当项目使用 TypeScript 时,defineProps 借助类型注解实现了强大的静态类型检查功能。这能在编码阶段就发现类型错误,大大提升了代码的可靠性和可维护性。

例如,创建一个展示用户列表的组件:

<template><ul><li v-for="user in props.users" :key="user.id">{{ user.name }} - {{ user.age }}岁</li></ul>
</template><script setup lang="ts">
interface User {id: number;name: string;age: number;
}const props = defineProps<{users: User[];
}>()
</script>

在这个示例中,首先定义了 User 接口明确用户对象的结构和属性类型。然后,通过 <{ users: User[]; }> 这种类型注解方式,告知 defineProps 该组件期望接收名为 users 的 props,其值是 User 类型的数组。这样,在父组件传递数据时,TypeScript 会严格检查数据类型是否匹配,若不匹配,编辑器会立即给出错误提示,帮助开发者及时发现并修复问题。

2 props 的类型与验证

2.1 支持的类型

defineProps 支持多种数据类型声明,为处理不同类型数据提供了极大的灵活性。

2.1.1 基础类型

常见的基础类型包括 String、Number、Boolean用于接收简单的文本、数值和布尔值数据。

例如,在展示商品价格的组件中:

<template><div><p>商品价格:{{ props.price }}</p></div>
</template><script setup>
const props = defineProps({price: {type: Number,required: true}
})
</script>

这里,price 被声明为必需的 Number 类型,确保组件接收的数据中 price 一定是有效的数值。

2.1.2 Object 和 Array 类型

除了基础类型,defineProps 还支持 Object Array 类型,用于处理复杂的数据结构。比如,在一个展示用户列表的组件中,我们可以接收一个包含用户信息的对象数组:

<template><ul><li v-for="user in props.users" :key="user.id">{{ user.name }} - {{ user.age }}岁</li></ul>
</template><script setup>
const props = defineProps({users: {type: Array,default: () => []}
})
</script>

这里的 users 是一个 Array 类型的 props ,并且设置了默认值为空数组,以防止在父组件未传递数据时出现错误。

2.1.3 Function 类型

defineProps 还支持 Function 类型,用于接收函数作为 props ,这在一些需要传递回调函数的场景中非常有用。

例如,在一个按钮组件中,我们可以接收一个点击事件的回调函数:

<template><button @click="props.clickHandler">点击我</button>
</template><script setup>
const props = defineProps({clickHandler: {type: Function,required: true}
})
</script>

在这个例子中,父组件可以传递一个函数给 clickHandler ,当按钮被点击时,就会执行这个回调函数。

2.1.4 其他类型

除了上述常见类型,defineProps 还支持许多高级类型,如枚举类型、对象类型、联合类型等。以联合类型为例,假设我们有一个组件,它可以接收字符串或者数字类型的 id :

<template><div><p>ID: {{ props.id }}</p></div>
</template><script setup lang="ts">
const props = defineProps<{id: string | number;
}>()
</script>

在这个示例中,id 被声明为 string 或 number 类型的联合类型,这意味着父组件可以传递字符串类型的 id ,也可以传递数字类型的id ,组件都能正确处理。

2.2 验证方式

为了确保组件接收到的数据符合预期,我们可以对 props 进行验证。defineProps 提供了多种验证方式,包括 type、required、default 和 validator 。

2.2.1 type

type 用于定义数据的类型,这是最基本的验证方式。通过明确指定 props 的类型,Vue 在运行时会检查传入的数据是否符合类型要求,如果不符合,会在控制台抛出警告。例如:

<template><div><p>姓名:{{ props.name }}</p></div>
</template><script setup>
const props = defineProps({name: {type: String}
})
</script>

在这个例子中,name 被定义为 String 类型,如果父组件传递的 name 不是字符串类型,Vue 就会发出警告。

2.2.2 required

required 用于指定 props 是否为必需。当设置为 true 时,如果父组件没有传递该 props ,Vue 同样会在控制台抛出警告。比如:

<template><div><p>订单编号:{{ props.orderId }}</p></div>
</template><script setup>
const props = defineProps({orderId: {type: String,required: true}
})
</script>

在这个场景中,orderId 是必需的字符串类型 props ,如果父组件没有传递 orderId ,则会触发警告,提醒开发者检查数据传递是否完整。

2.2.3 default

default 用于设置 props 的默认值。当父组件没有传递该 props 时,组件会使用默认值。默认值的设置方式根据 props 的类型而有所不同。对于简单类型,如字符串、数字、布尔值等,可以直接设置默认值;对于对象和数组类型,需要通过函数返回默认值,以确保每次使用默认值时都是一个新的实例,避免引用类型数据的共享问题。例如:

<template><div><p>提示信息:{{ props.tip }}</p></div>
</template><script setup>
const props = defineProps({tip: {type: String,default: '暂无提示信息'},userInfo: {type: Object,default: () => ({})}
})
</script>

在这个例子中,tip的默认值是一个字符串,而 userInfo 的默认值是一个空对象,通过函数返回,保证了每次使用默认值时都是一个新的空对象。

2.2.4 validator

validator 是一个自定义验证函数,用于对 props 进行更复杂的验证逻辑。该函数接收一个参数,即父组件传递过来的 props 值,函数返回 true 表示验证通过,返回 false 则表示验证失败,验证失败时 Vue 会在控制台抛出警告。比如,我们要验证一个表示年龄的 props ,要求年龄必须在 18 到 100 之间:

<template><div><p>年龄:{{ props.age }}</p></div>
</template><script setup>
const props = defineProps({age: {type: Number,validator: (value) => {return value >= 18 && value <= 100}}
})
</script>

在这个示例中,validator 函数会检查 age 的值是否在 18 到 100 之间,如果不在这个范围内,就会验证失败,提示开发者传入的年龄不符合要求。

通过 type、required、default 和 validator 这些验证方式的结合使用,我们可以确保组件接收到的数据的有效性和完整性,提高应用的稳定性和可靠性。

3 Vue3.5 中 defineProps 的新特性

Vue 3.5 的发布为 defineProps 带来了一些令人欣喜的新特性,这些特性进一步提升了开发的便利性和效率,让我们一起来深入了解一下。

3.1 响应式 Props 解构

在 Vue3.5 之前,如果我们直接对 props 进行解构赋值,会失去响应式,需要配合使用 toRefs 或者 toRef 解构才会有响应式 ,这无疑增加了开发的工序和代码的复杂性。

例如,在一个简单的计数器组件中,假设父组件传递一个 count 属性给子组件 :

<template><div><p>{{ count }}</p><button @click="increment">增加</button></div>
</template><script setup lang="ts">
import { toRef } from 'vue'
const props = defineProps<{count: number
}>()
const count = toRef(props, 'count')
const increment = () => {count.value++
}
</script>

在这段代码中,为了保持 count 的响应式,我们不得不使用 toRef 将 props.count 转换为一个响应式的 ref ,这使得代码显得有些繁琐。

而在 Vue3.5 中,我们可以直接进行响应式解构,无需借助额外的工具函数 。同样是上述计数器组件,代码可以简化为:

<template><div><p>{{ count }}</p><button @click="increment">增加</button></div>
</template><script setup lang="ts">
const { count } = defineProps<{count: number
}>()
const increment = () => {count++
}
</script>

可以看到,直接解构 defineProps 返回的值,count 依然保持着响应式,当父组件的 count 值发生变化时,子组件会自动更新,反之亦然。这种方式极大地简化了代码,提高了开发效率,让我们的代码更加简洁、直观。Vue 3.5 对解构变量(例如count)的访问会被编译器自动编译成props.count,因此访问时会对其进行跟踪,确保了响应式的正常工作。 这一特性在处理复杂的props 结构时,优势更加明显。比如,当我们需要从一个包含多个属性的对象中解构出多个响应式属性时,Vue3.5 之前的写法会非常冗长,而现在则可以轻松实现。

3.2 新的默认值写法

在 Vue3.5 之前,设置 props的默认值需要使用 default 选项,例如:

<template><div><p>{{ message }}</p></div>
</template><script setup>
const props = defineProps({message: {type: String,default: '默认消息'}
})
</script>

这种写法在定义简单的 props 默认值时还不算复杂,但当props较多或者默认值的逻辑较为复杂时,代码会显得比较臃肿。

3.2.1 使用 JavaScript 原生默认值语法

Vue3.5 中,可使用 JavaScript 原生默认值语法设置 props 默认值,使代码更简洁。例如:

<template><div><p>{{ message }}</p></div>
</template><script setup>
const { message = '默认消息' } = defineProps({message: String
})
</script>

在这个例子中,我们直接在解构时为 message 设置了默认值,这种写法更接近 JavaScript 的常规语法,大大降低了开发者的学习成本和心智负担 。特别是在使用基于类型的 props 声明时,这种新的默认值写法更加简洁高效。例如,在 TypeScript 中:

<template><div><p>{{ count }}</p></div>
</template><script setup lang="ts">
const { count = 0 } = defineProps<{count?: number
}>()
</script>

通过这种方式,我们可以清晰地看到 count 的类型和默认值,代码的可读性和可维护性都得到了显著提升。 新的默认值写法不仅适用于简单类型,对于对象和数组等复杂类型同样适用。比如,当我们需要为一个包含多个属性的对象设置默认值时,可以这样写:

<template><div><p>{{ user.name }}</p><p>{{ user.age }}</p></div>
</template><script setup lang="ts">
const { user = { name: '张三', age: 18 } } = defineProps<{user?: {name: stringage: number}
}>()
</script>

这样,当父组件没有传递 user 属性时,子组件会使用默认的 user 对象,并且代码结构更加紧凑,易于理解。

3.2.2 使用 withDefaults 函数

withDefaults 是 Vue 3.5 引入的新特性,专门用于设置 props 的默认值,同时能提供良好的类型支持。

<template><div><p>{{ message }}</p></div>
</template><script setup lang="ts">
import { defineProps, withDefaults } from 'vue';const props = withDefaults(defineProps<{message?: string;
}>(), {message: () => '默认消息'
});const { message } = props;
</script>

defineProps 定义 props 类型,withDefaults 设置默认值,两者结合使代码结构更清晰,类型检查更严格。

4 综合展示

为全面展示 Vue3.5 中 defineProps 的用法,来看一个完整的父子组件通信示例。假设开发一个简单电商应用,有父组件 ProductList 展示商品列表,子组件 ProductItem 展示单个商品详细信息。

首先,创建父组件 ProductList.vue

<template><div><h1>商品列表</h1><ProductItemv-for="product in products":key="product.id":product="product"@addToCart="addToCart"/></div>
</template><script setup lang="ts">
import ProductItem from './ProductItem.vue'
import { ref } from 'vue'// 模拟商品数据
const products = ref([{id: 1,name: 'Vue.js 实战指南',price: 59.99,description: '一本深入学习Vue.js的书籍'},{id: 2,name: '智能手表',price: 199.99,description: '具备多种健康监测功能的智能手表'}
])// 模拟添加商品到购物车的方法
const addToCart = (product) => {console.log(`已将 ${product.name} 添加到购物车`)
}
</script>

父组件定义了 products 数组,包含两个商品对象。通过 v-for 指令将每个商品对象传递给ProductItem 子组件,并绑定 product 属性。同时定义 addToCart 方法处理添加商品到购物车的逻辑,作为事件监听器传递给子组件。

接下来,创建子组件 ProductItem.vue

<template><div class="product-item"><h2>{{ product.name }}</h2><p>价格: {{ product.price }}</p><p>描述: {{ product.description }}</p><button @click="handleAddToCart">添加到购物车</button></div>
</template><script setup lang="ts">
const { product } = defineProps<{product: {id: numbername: stringprice: numberdescription: string}
}>()const emit = defineEmits(['addToCart'])const handleAddToCart = () => {emit('addToCart', product)
}
</script><style scoped>
.product-item {border: 1px solid #ccc;padding: 10px;margin: 10px;
}
</style>

子组件使用 Vue3.5 新特性,直接对 defineProps 进行响应式解构获取 product 对象。定义handleAddToCart 方法,用户点击 “添加到购物车” 按钮时,触发 addToCart 事件,并将当前商品对象传递给父组件。

通过这个综合示例,能清晰看到 Vue3.5 中defineProps在父子组件通信中的实际应用。利用响应式 Props 解构,子组件可以更便捷地访问和使用从父组件传递过来的数据,代码简洁且直观。同时,结合defineEmits实现了子组件向父组件传递数据和事件的功能,完整地展示了 Vue 组件间通信的双向流程。这不仅提升了开发效率,还增强了代码的可读性和可维护性,使得整个组件化开发过程更加流畅。

在实际项目开发中,defineProps的这些特性能够帮助开发者更高效地构建大型应用程序。无论是简单的展示组件,还是复杂的业务逻辑组件,都可以根据具体需求灵活运用 defineProps 的不同声明方式和验证机制,确保组件间数据传递的准确性和稳定性。而 Vue3.5 引入的新特性,更是为开发者在处理响应式数据和设置默认值等常见场景下,提供了更为简洁、强大的工具,进一步降低了开发成本,推动 Vue 应用开发迈向更高的效率和质量水平。随着 Vue 框架的不断发展和更新,相信defineProps以及相关功能还会持续优化,为广大前端开发者带来更多便利和惊喜 。

下一篇将探讨menu组件,敬请期待~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/16328.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【力扣】148.排序链表

AC截图 题目 思路 基本情况处理&#xff1a; 如果链表为空 (head NULL) 或者链表仅有一个节点 (head->next NULL)&#xff0c;则链表已经是有序的&#xff0c;直接返回头节点 head。 分割链表&#xff1a; 使用快慢指针法找到链表的中间节点。slow 指针每次前进一格&…

新数据结构(7)——Object

Object类是所有类的父类&#xff0c;也就是说所有类都是object类的子类可以使用Object里的方法。 equals()和hashCode()是Object包含的方法 和equals的区别和联系 和equals()都是用于判断是否相等 基本数据类型只能用判断其是否相等&#xff0c;引用数据类型用判断的是其指…

保研考研机试攻略:python笔记(4)

🐨🐨🐨15各类查找 🐼🐼二分法 在我们写程序之前,我们要定义好边界,主要是考虑区间边界的闭开问题。 🐶1、左闭右闭 # 左闭右闭 def search(li, target): h = len(li) - 1l = 0#因为都是闭区间,h和l都可以取到并且相等while h >= l:mid = l + (h - l) // 2…

doris集群

开发doris的团队厉害&#xff0c;这个百度工程师确实也干了一些实事&#xff0c;不像领导层只会跑火车。 1 参数配置 1.1 文件句柄数 vim /etc/security/limits.conf * soft nofile 655350 * hard nofile 6553501.2 关闭透明大页 echo never > /sys/kernel/mm/transpare…

STM32的HAL库开发---高级定时器---互补输出带死区实验

一、互补输出简介 互补输出&#xff1a;OCx输出高电平&#xff0c;则互补通道OCxN输出低电平。OCx输出低电平&#xff0c;则互补通道OCxN输出高电平。 带死区控制的互补输出&#xff1a;OCx输出高电平时&#xff0c;则互补通道OCxN过一会再输出输出低电平。这个时间里输出的电…

京东广告生成式召回基于 NVIDIA TensorRT-LLM 的推理加速实践

0000 生成式推荐系统优势介绍 推荐系统的主要任务是根据用户的历史行为预测其兴趣点&#xff0c;并向其推荐相应的商品。传统的推荐系统在处理用户请求时&#xff0c;会触发多个召回模块&#xff08;包括热门商品召回、个性化召回、深度召回等&#xff09;&#xff0c;以召回大…

3.React 组件化开发

react&#xff1a;版本 18.2.0node&#xff1a; 版本18.19.1脚手架&#xff1a;版本 5.0.1 一、类组件 (一) 一个干净的脚手架 【1】使用已经被废弃的 CRA (create-react-app) create-react-app 已经被废弃&#xff0c;且目前使用会报错&#xff0c;官方已经不推荐使用&…

51单片机(国信长天)矩阵键盘的基本操作

在CT107D单片机综合训练平台上&#xff0c;首先将J5处的跳帽接到1~2引脚&#xff0c;使按键S4~S19按键组成4X4的矩阵键盘。在扫描按键的过程中&#xff0c;发现有按键触发信号后(不做去抖动)&#xff0c;待按键松开后&#xff0c;在数码管的第一位显示相应的数字:从左至右&…

【AI赋能】蓝耘智算平台实战指南:3步构建企业级DeepSeek智能助手

蓝耘智算平台实战指南&#xff1a;3步构建企业级DeepSeek智能助手 引言&#xff1a;AI大模型时代的算力革命 在2025年全球AI技术峰会上&#xff0c;DeepSeek-R1凭借其开源架构与实时推理能力&#xff0c;成为首个通过图灵测试的中文大模型。该模型在语言理解、跨模态交互等维…

机器学习 - 词袋模型(Bag of Words)实现文本情感分类的详细示例

为了简单直观的理解模型训练&#xff0c;我这里搜集了两个简单的实现文本情感分类的例子&#xff0c;第一个例子基于朴素贝叶斯分类器&#xff0c;第二个例子基于逻辑回归&#xff0c;通过这两个例子&#xff0c;掌握词袋模型&#xff08;Bag of Words&#xff09;实现文本情感…

没有服务器和显卡电脑如何本地化使用deepseek|如何通过API使用满血版deepseek

目录 一、前言二、使用siliconflow硅基流动 API密钥1、注册硅基流动2、创建API密钥3、下载AI客户端4、使用API密钥5、效果演示 三、使用deepseek官方API密钥1、创建API密钥2、使用API密钥3、效果演示 四、总结 一、前言 上篇文章我介绍了如何通过云服务器或者显卡电脑来本地化…

算法学习笔记之贪心算法

导引&#xff08;硕鼠的交易&#xff09; 硕鼠准备了M磅猫粮与看守仓库的猫交易奶酪。 仓库有N个房间&#xff0c;第i个房间有 J[i] 磅奶酪并需要 F[i] 磅猫粮交换&#xff0c;硕鼠可以按比例来交换&#xff0c;不必交换所有的奶酪 计算硕鼠最多能得到多少磅奶酪。 输入M和…

oracle执行grant授权sql被阻塞问题处理

一 问题描述 执行普通的grant授权sql(grant select,update on 表名 to 用户名)好几分钟都没反应&#xff0c;跟被阻塞了似的。 二 问题排查 #排查是否有阻塞 用OEM可以看到阻塞信息&#xff1a; 点‘性能’-‘阻塞会话’&#xff1a; 下面那个会话2958是我执行grant sql的…

SSM仓库物品管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1.用户登录代码&#xff1a;2.保存物品信息代码&#xff1a;3.删除仓库信息代码&#xff1a; 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SSM框架开发的仓库…

Deepseek 接入Word处理对话框(隐藏密钥)

硅基流动邀请码&#xff1a;1zNe93Cp 邀请链接&#xff1a;网页链接 亲测deepseek接入word&#xff0c;自由调用对话&#xff0c;看截图有兴趣的复用代码&#xff08;当然也可以自己向deepseek提问&#xff0c;帮助你完成接入&#xff0c;但是提问逻辑不一样给出的答案是千差万…

Docker Compose介绍及安装使用MongoDB数据库详解

在现代容器化应用部署中&#xff0c;Docker Compose是一种非常实用的工具&#xff0c;它允许我们通过一个docker-compose.yml文件来定义和运行多容器应用程序。然而&#xff0c;除了Docker之外&#xff0c;Podman也提供了类似的工具——Podman Compose&#xff0c;它允许我们在…

IntelliJ IDEA Console控制台输出成json的配置方式

【IntelliJ IDEA Console控制台输出成json的配置方式】 1.帮助->查找操作 2.搜索注册表 3.ctrlf 搜索pty 控制台右键 结果

基础入门-HTTP数据包红蓝队研判自定义构造请求方法请求头修改状态码判断

知识点&#xff1a; 1、请求头&返回包-方法&头修改&状态码等 2、数据包分析-红队攻击工具&蓝队流量研判 3、数据包构造-Reqable自定义添加修改请求 一、演示案例-请求头&返回包-方法&头修改&状态码等 数据包 客户端请求Request 请求方法 …

react redux用法学习

参考资料&#xff1a; https://www.bilibili.com/video/BV1ZB4y1Z7o8 https://cn.redux.js.org/tutorials/essentials/part-5-async-logic AI工具&#xff1a;deepseek&#xff0c;通义灵码 第一天 安装相关依赖&#xff1a; 使用redux的中间件&#xff1a; npm i react-redu…

机器学习 - 线性回归(最大后验估计)

最大似然估计的一个缺点是当训练数据比较少时会发生过拟合&#xff0c;估计的参数可能不准确.为了避免过拟合&#xff0c;我们可以给参数加上一些先验知识. 一、先从最大似然估计的一个缺点入手 最大似然估计&#xff08;MLE&#xff09;在处理小样本数据时&#xff0c;容易发…