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

Vue3核心语法进阶(Props)

 Vue3 中的 Props:父子组件的“传话筒”详解

接下来我们来聊聊 Vue3 中一个超级基础但又极其重要的概念——Props

如果你已经会用 Vue 写组件,那你一定用过 props。但你真的完全理解它吗?比如:

  • 为什么子组件不能直接改 props?
  • 什么时候该用 .sync 或 v-model
  • 如何给 props 加类型验证和默认值?

别急!今天我就用比喻,带你彻底搞懂 Vue3 的 Props,让你从“会用”变成“精通”!


什么是 Props?(一句话说清)

Props 就是父组件传给子组件的数据,相当于“父子之间的传话筒”。

想象一下:你爸(父组件)想让你(子组件)去超市买牛奶,他会告诉你:

  • 买什么?—— 牛奶
  • 买几瓶?—— 2 瓶
  • 什么牌子?—— 蒙牛

这些信息,就是 Props

<!-- 父组件 App.vue -->
<template><BuyMilk item="牛奶" count="2" brand="蒙牛" />
</template>
<!-- 子组件 BuyMilk.vue -->
<script setup>
// 接收父组件传来的数据
defineProps(['item', 'count', 'brand'])
</script><template><div>我要去买 {{ count }} 瓶 {{ brand }} {{ item }}!</div>
</template>

输出结果:我要去买 2 瓶 蒙牛 牛奶!

这就是 Props 的最基本用法:父传子,单向数据流


如何在 Vue3 中定义 Props?

Vue3 推荐使用 <script setup> + defineProps(),它是一个编译宏(不需要引入),写起来超简单!

方式一:数组写法(简单场景)

defineProps(['title', 'content', 'author'])

适合快速原型,但不推荐生产环境用,因为没类型、没默认值。

方式二:对象写法(推荐!)

defineProps({title: String,content: String,author: {type: String,default: '匿名用户'},likes: {type: Number,default: 0},isActive: {type: Boolean,default: true}
})

 这才是专业写法!支持类型、默认值、必填校验等。


讲解:Props 的“只读性”(为什么不能改?)

这是新手最容易踩的坑!

错误示范:

const props = defineProps(['count'])// 想要增加数量?
props.count++ //  警告!不要直接修改 props!

为什么不能改?

因为 Props 是“只读”的,就像你爸告诉你“买 2 瓶牛奶”,你不能偷偷改成“买 3 瓶”然后说“爸说的”!

Vue 的设计哲学是:数据流向要清晰。父组件传数据,子组件只能用,不能私自篡改。


那我想改怎么办?—— 用 emit 反向通知!

正确的做法是:子组件通过 emit 告诉父组件:“我想改数据”,然后由父组件决定是否修改。

示例:一个可增减的计数器

<!-- 子组件 Counter.vue -->
<script setup>
const props = defineProps(['count'])
const emit = defineEmits(['update:count'])const increase = () => {emit('update:count', props.count + 1)
}const decrease = () => {emit('update:count', props.count - 1)
}
</script><template><div><button @click="decrease">-</button>{{ count }}<button @click="increase">+</button></div>
</template>
<!-- 父组件 App.vue -->
<script setup>
import { ref } from 'vue'
import Counter from './Counter.vue'const myCount = ref(5)
</script><template><Counter :count="myCount" @update:count="myCount = $event"/>
</template>

看到了吗?子组件不能自己改,但可以“申请修改”,父组件同意了才算数!


语法糖:v-model 和 .sync 的秘密

上面的 @update:count 写起来有点啰嗦?Vue 提供了语法糖!

方式一:用 v-model(最常用)

<!-- 父组件 -->
<Counter v-model="myCount" /><!-- 等价于 -->
<Counter :count="myCount" @update:count="myCount = $event"
/>

注意:默认 v-model 对应的是 modelValueupdate:modelValue

如果你想用别的名字,比如 v-model:count

<!-- 子组件 -->
defineProps(['count'])
defineEmits(['update:count'])<!-- 父组件 -->
<Counter v-model:count="myCount" />

方式二:.sync 修饰符(Vue2 遗留,Vue3 仍支持)

<!-- 父组件 -->
<Counter :count.sync="myCount" /><!-- 等价于 -->
<Counter :count="myCount" @update:count="myCount = $event"
/>

推荐用 v-model,更现代、更清晰。


Props 高级用法:类型、默认值、验证

1. 支持复杂类型

defineProps({userInfo: {type: Object,default: () => ({ name: '张三', age: 20 })},tags: {type: Array,default: () => ['前端', 'Vue']}
})

 对象和数组的 default 必须是函数,否则会共享引用!

2. 自定义验证函数

defineProps({status: {type: String,validator(value) {// 只允许这几个值return ['active', 'inactive', 'pending'].includes(value)}}
})

传错会直接在控制台报错,开发时非常有用!

3. 必填项

defineProps({requiredId: {type: Number,required: true}
})

如果父组件没传,Vue 会警告你。


常见问题 & 最佳实践

Q1:Props 是响应式的吗?

是的! 只要父组件的数据变了,子组件的 props 会自动更新。

但记住:不要在子组件中直接修改它

Q2:我可以给 Props 加 ref 吗?

不要这么做!比如:

const myProp = ref(props.count) // 错误!断开了响应式连接

如果你需要基于 props 做计算,用 computed

import { computed } from 'vue'
const doubleCount = computed(() => props.count * 2)

最佳实践总结

建议说明
用对象形式定义 Props支持类型、默认值、验证
对象/数组 default 写成函数避免引用共享
不要直接修改 Props用 emit 通知父组件
复杂逻辑用 computed 或 watch保持响应式
用 v-model 简化双向绑定代码更简洁

总结:Props 核心要点

概念说明
作用父组件向子组件传递数据
特性单向数据流、只读
修改方式子组件 emit,父组件修改
语法糖v-model.sync 简化写法
安全支持类型、默认值、自定义验证

最后一句话

Props 是组件通信的“高速公路”,但它是单行道——数据只能从父到子。

想要“反向开车”?请走 emit 的“匝道”,由父组件决定是否放行!

掌握好 Props,你的组件才能既灵活安全

http://www.xdnf.cn/news/17020.html

相关文章:

  • 【C# Winform】 Action事件驱动的多层数据传递
  • 8.5PPT总结各种攻击
  • 37.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--增加Github Action
  • Linux NFS 服务部署、客户端配置及 autofs 自动挂载操作指南
  • 嵌入式硬件中运放内部底层分析
  • 区块链:重构信任的价值互联网革命​
  • CNN卷积神经网络之注意力机制CBAM(六)
  • 【android bluetooth 协议分析 01】【HCI 层介绍 30】【hci_event和le_meta_event如何上报到btu层】
  • uniapp Android App集成支付宝的扫码组件mPaaS
  • Linux 内存管理之 Rmap 反向映射(二)
  • Kafka-Eagle 安装
  • 江协科技STM32学习笔记1
  • AlexNet训练和测试FashionMNIST数据集
  • 什么是越权漏洞?如何验证。
  • c++介绍
  • cJSON库应用
  • Python高级编程与实践:Python装饰器深入解析与应用
  • 【数据结构初阶】--排序(三):冒泡排序,快速排序
  • BeeWorks私有化即时通讯,局域网办公安全可控
  • Python基础框架
  • 改进的BP神经网络算法用于预测温度值的变化
  • 剑指offer第2版:字符串
  • jenkins插件Active Choices的使用通过参数动态控制多选参数的选项
  • java web 未完成项目,本来想做个超市管理系统,前端技术还没学。前端是个简单的html。后端接口比较完善。
  • mq_timedsend系统调用及示例
  • 朴素贝叶斯(Naive Bayes)算法详解
  • 使用 ECharts 实现小区住户数量统计柱状图
  • 豆包新模型与 PromptPilot 实操体验测评,AI 辅助创作的新范式探索
  • 涨薪技术|Kubernetes(k8s)之Pod生命周期(上)
  • 山东省天地图API申请并加载到QGIS和ArcGIS Pro中