vue3 Props的用法(父传子)

news2024/11/16 5:24:06

在 Vue 3 中,Props(属性)用于在组件之间传递数据。

Props的作用

  1. 传参:Props 允许父组件向子组件传递数据。
  2. 类型检查:Vue 允许在定义 Props 时指定数据的类型,这有助于在开发过程中进行类型检查,提前发现潜在的类型错误。
  3. 设置默认值:可以为 Props 设置默认值。当父组件没有传递该 Prop 时,子组件会使用默认值进行渲染。

Vue 中的 Props 遵循单向数据流原则,即父组件向子组件传递数据,子组件不能直接修改父组件传递过来的 Prop。

父组件传值给子组件

在父组件的模板中,可以使用属性绑定的方式将数据传递给子组件(静态传值):

<ChildComponent title="哈嘿" />

可以使用变量或表达式来动态地传递 Props:

<!-- 根据一个变量的值动态传入 -->
<ChildComponent :title="title" />
 
<!-- 根据一个更复杂表达式的值动态传入 -->
<ChildComponent :title="someCondition ? titleA : titleB" />

可以使用 v-bind 动态绑定所有的 props:
可以将一个对象传递给 v-bind,这个对象的属性将被用作组件的 props。

<template>
  <ChildComponent v-bind="obj" />
</template>

<script setup lang="ts">
import ChildComponent from './ChildComponent.vue';
import { reactive } from 'vue'
let obj = reactive({
  message: 'Hello',
  count: 5
})
</script>

<ChildComponent v-bind="obj" /> 等价于:

<ChildComponent :message="message" :count="count" />

声明 Props

  1. 使用 defineProps 函数:
    • <script setup> 语法中,可以直接使用 defineProps 函数来声明组件接收的 Props。
<script setup lang="ts">
import { defineProps } from 'vue';

// 字符串数组形式
const props = defineProps(['message', 'count']);
</script>

在这个例子中,声明了两个 Props:messagecount

可以使用对象字面量的方式来声明 Props:

<script setup lang="ts">
import { defineProps } from 'vue';

const props = defineProps({
  message: String,
  count: Number,
});
</script>

在这个例子中,声明了两个 Props:message 是字符串类型,count 是数字类型。
<script setup> 语法中,使用 defineProps 函数结合类型注解来进行基于类型的声明
如果项目没有使用 TypeScript,就无法使用基于类型的声明进行声明。
基于类型的声明可以在开发过程中利用 TypeScript 的类型检查机制,提前发现类型错误。

  1. 如果没有使用 <script setup> 语法糖, 可以使用 props 选项来声明。
    • 必须要用props选项声明组件接收的Props,在setup()props参数里,才有Props数据。
export default {
  props: ['message'],
  setup(props) {
    // setup() 接收 props 作为第一个参数
    console.log(props.message)
  }
}

必须要用props选项声明组件接收的Props。如果没有 props: ['message']

export default {
  setup(props) {
    // 报错: 类型“LooseRequired<{} & {}>”上不存在属性“message”。
    console.log(props.message)  
  }
}

通过在组件选项对象中直接定义 props 属性来进行运行时声明

export default {
  props: {
    message: String,
    count: Number,
  },
  // 组件的其他选项和逻辑
};

在这个例子中,message 被声明为字符串类型的 Prop,count 被声明为数字类型的 Prop。这种方式在运行时,Vue 会根据声明的类型对传入的 Props 进行验证。

运行时声明通常在不需要进行严格类型检查或者需要更灵活地处理 Props 的情况下使用。它主要依赖于 Vue 的运行时机制来处理 Props 的传递和验证。

传递给 defineProps() 的参数和提供给 props 选项的值是相同的,本质上都是在使用 prop 选项。

Props 的验证

Props 验证的主要目的是确保组件接收到的数据符合预期的格式和类型。

类型验证

  • 可以指定 Props 的类型,如 StringNumberBooleanArrayObject 等。
  • 也可以是函数类型 Function 、自定义类型。
<script setup lang="ts">
import { defineProps } from 'vue';
// 定义一个接口作为自定义类型
interface MyCustomType{
  property1: string;
  property2: number;
}
const props = defineProps({
  name: String,
  age: Number,
  hobbies: Array,
  address: Object,
  customType: MyCustomType, // 自定义类型
  onButtonClick: Function   // 函数类型
});
</script>

确保父组件传递给子组件的Props值与声明的类型一致,避免类型错误。

必需性

- 可以指定 Props 是否为必需,如果为必需,则必须在父组件中传入。
<script setup lang="ts">
import { defineProps } from 'vue';

const props = defineProps({
  message: {
    type: String,
    required: true
  }
});
</script>

在这个例子中,message 是必需的 Prop,如果父组件没有传递 message ,则会抛出警告。

自定义验证

- 可以使用 validator 函数进行自定义验证。
<script setup lang="ts">
import { defineProps } from "vue";

let props = defineProps({
  b: {
    type: Number,
    validator: (value: number) => {
      return value >= 0; // 自定义验证,确保宽度非负
    }
  }
})
console.log(props)
</script>

在这个例子中,b 使用了自定义验证函数,确保b 的值不为负数。
在父组件传入b = -10,浏览器控制台输出警告:
在这里插入图片描述

默认值

可以为 Props 设置默认值,当父组件没有传递该 Prop 时,子组件会使用默认值进行渲染。

<script setup lang="ts">
import { defineProps } from 'vue';

const props = defineProps({
  message: {
    type: String,
    default: 'Hello, Vue 3!',
  },
  count: {
    type: Number,
    default: 0,
  },
});
</script>

在这个例子中,message 的默认值为 'Hello, Vue 3!'count 的默认值为 0

withDefaults

在 Vue 3 中,withDefaults 是一个用于为 defineProps 定义的 props 设置默认值的函数。

withDefaults 参数说明:

  • withDefaults 的第一个参数是 defineProps 的返回值,它表示组件接收的 props 对象。
  • 第二个参数是一个对象,其中的键对应于 props 的名称,值是相应的默认值。
    • 默认值是通过函数返回的。

假设有一个组件,定义了一些 props,并且希望为其中一些 props 设置默认值:

<template>
  <div>{{ props.message }}</div>
  <div>{{ props.count }}</div>
</template>
<script setup lang="ts">
import { defineProps, withDefaults } from 'vue';

// 定义了一个接口 PropsInter  来描述组件的 props 结构
interface PropsInter {
  message: string;
  count: number;
  obj: { a: number; b: number; };
  arr: string[];
}

const props = withDefaults(defineProps<PropsInter>(), {
  message: 'Hello, Vue 3!',
  count: 0,
  obj: () => {
  	return { a: 10, b: 5 }
  },
  arr: () => return [ 'item1', 'item2' ]
});
</script>

Boolean 类型转换

当声明为 Boolean 类型的 props 时,有特别的类型转换规则,以便更贴近原生的 boolean attributes 的行为。

  • 当一个 prop 明确被声明为布尔类型时,真值会被转换为 true,假值会被转换为 false
    • 当父组件传递一个真值(如 true、字符串 "true"、数字 1 等)时,该 prop 将被转换为 true
    • 当父组件传递一个假值(如 false、字符串 "false"、数字 0、空字符串 ""nullundefined 等)时,该 prop 将被转换为 false

在子组件中:

defineProps({
  disabled: Boolean
})

在父组件中:

<!-- 等同于传入 :disabled="true" -->
<MyComponent disabled />
 
<!-- 等同于传入 :disabled="false" -->
<MyComponent />
  • 当一个 prop 被声明为允许多种类型时,声明顺序会影响 Boolean 转换规则是否适用:
    • 当同时允许字符串和布尔类型时,如果布尔类型出现在字符串类型之前,Boolean 转换规则才适用。
const props = defineProps({
  myProp: [Boolean, String],
});

如果父组件传递 "true",这个值将被转换为布尔值 true。如果传递 "false",将被转换为布尔值 false。其他字符串值将保持为字符串。
但是,如果声明顺序是 [String, Boolean],那么 "true""false" 将被视为字符串,而不会进行布尔类型的转换。

这种边缘情况可能会导致在不同的声明顺序下,相同的输入值被解释为不同的类型。

使用 Props

在父组件的模板中传值给子组件:

<ChildComponent title="哈嘿" />

在子组件的模板中,可以直接使用定义的 Props:

<template>
  <div>{{ title }}</div>
</template>
<script setup lang="ts" name="ChildComponent">
import { defineProps } from "vue";
defineProps(['title'])

// console.log(title)  // 报错:找不到名称“title”。
</script>

在模板中,可以直接使用title
console.log(title) 报错:找不到名称“title”。
这是因为title 并没有被直接声明为一个可用的变量。

在 Vue 3 的 <script setup> 中,defineProps 的返回值是一个包含传入的 props 的对象。

如果想要在组件中使用 title ,需要通过defineProps的返回值来读取:

<template>
  <div>{{ props.title }}</div>
</template>
<script setup lang="ts" name="ChildComponent">
import { defineProps } from "vue";
// 只接收title属性
let props = defineProps(['title'])

console.log(props)

if(props.title) {
  console.log(props.title)
}
</script>

defineProps 返回一个对象 propsprops 对象中包含了 title 属性,可以通过 props.title 的方式来访问和使用这个 prop 的值。
在这里插入图片描述

defineProps 的返回值是一个包含组件接收的 props 的只读对象:

  • 返回的 props 对象是只读的。
  • 返回的 props 对象包含了组件所有接收的东西:父组件传递给当前组件的所有被组件明确声明为 props 的属性。
    • 必须在defineProps中显式的接收父组件传递的属性。假如父组件传了几个属性,比如<ChildComponent title="哈嘿" id="id12345" />,子组件defineProps(['title'])只接收title属性,不会接收id属性。
  • 在组件内部不能直接修改 props 对象的属性值。

实战演练

types/index.ts定义一个PersonInter接口:

// 定义一个接口,用于限制对象的具体属性
// 接口在 TypeScript 中用于定义一种契约,确保实现该接口的对象都具有相同的结构。
export interface PersonInter {
  id: string;
  name: string;
  age: number;
}

在父组件有一个person传递给子组件:

<template>
  <div>
    <ChildComponent :personList="personList" />
  </div>
</template>

<script setup lang="ts" name="Person">
// 在 TypeScript 中,import type 语法用于仅导入类型信息而不导入实际的值或函数。
// 使用 import type 导入的类型信息仅在类型检查时使用,不会在运行时产生任何影响。
import type { PersonInter } from '@/types';

import { reactive } from 'vue';
import ChildComponent from './ChildComponent.vue';
let personList = reactive<PersonInter>({
  id: 'person001',
  name: 'John',
  age: 18
});
</script>

子组件:

<template>
  <div>{{ person.name }}</div>
</template>
<script setup lang="ts" name="ChildComponent">
import type { PersonInter } from '@/types';
import { defineProps } from "vue";

// 只接收person
let props = defineProps(['person'])
console.log(props)

// 接收person+类型限制
let props = defineProps<{ person: PersonInter }>()

// 接收person+类型限制+限制必要性+默认值
// ?表示不必传,父组件可传可不传,如果父组件不传,则使用默认值
// 指定默认值需要使用withDefaults
withDefaults(defineProps<{ person?: PersonInter }>(), {
  person: () => {
    return { id: 'person000', name: 'Alice', age: 18 }
  }
})

</script>
  • let props = defineProps(['person']) 只接收person,对person没有任何限制。父组件可以给person赋任意类型的值。
  • defineProps<{ person: PersonInter }>(): 通过泛型参数指定了 props 的结构。具体来说,定义了一个名为 person 的 prop,其类型为 PersonInter
  • defineProps<{ person?: PersonInter }>():
    • 使用泛型参数指定了 props 的结构。定义了一个名为 person 的 prop,其类型为 PersonInter
    • 后面的问号 ? 表示这个 prop 是可选的,即父组件可以选择是否传递这个 prop。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nextjs(App Router) 开发记录

最近业余在开发一款智能助理产品&#xff0c;记录开发过程中的一些问题以备忘&#xff0c;也是帮其他人防坑。 主要技术栈 本项目采用了前沿的技术栈来构建一个高性能且可维护的应用。选择了 Nx 作为构建管理和单一代码库解决方案&#xff0c;通过模块化和插件系统来扩展和优…

开源的个人独立博客Moments社交优化项目源码

开源的个人独立博客Moments社交优化项目源码&#xff0c;为你提供了一个与关注的博客作者和读者互动的全新方式&#xff0c;让你的博客体验更加丰富和充实。 Moments的核心目标是通过整合各种订阅源&#xff0c;如RSS和Atom&#xff0c;将你感兴趣的博客转化为一个个人朋友圈。…

日志排查——linux

目录 介绍步骤 介绍 /var/log/wtmp&#xff1a;记录登录进入、退出、数据交换、关机和重启&#xff0c;即last。 /var/log/cron&#xff1a;记录与定时任务相关的日志信息。 /var/log/messages&#xff1a;记录系统启动后的信息和错误日志。 /var/log/apache2/access.log&a…

你不知道的console方法

JavaScript为我们提供了一个内置的调试工具&#xff0c;即控制台(console)&#xff0c;使开发人员能够测试、调试和与他们的网页进行交互。JavaScript的控制台对象中有几种可用的方法&#xff0c;每种方法都有不同的用途。本文将讨论这些方法&#xff0c;并提供它们的使用示例。…

计算机毕业设计 学院网站 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

Linux中解决 zfs 安装后无法加载和使用,报错类似如下:modprobe: FATAL: Module zfs not found.

Linux中解决 zfs 安装后无法加载和使用&#xff0c;报错类似如下&#xff1a;modprobe: FATAL: Module zfs not found. # modprobe zfs modprobe: FATAL: Module zfs not found.解决办法&#xff1a; yum remove zfs spl kmod-zfs -yyum update -y --skip-brokenos_v$(cat /et…

文献翻译什么软件好?文献翻译全文软件推荐这5个

处暑已过&#xff0c;秋风渐起&#xff0c;知识的田野也迎来了收获的季节。在学术研究的旅途中&#xff0c;我们常常需要跨越语言的界限&#xff0c;探寻远方的智慧。 每当面对厚重的外文文献&#xff0c;应该如何快速准确地转化为可读的中文呢&#xff1f;其实只要选择一款高…

加速指南:如何使用Kimi提升论文写作效率?

在学术研究领域&#xff0c;撰写论文是一项基础且关键的任务&#xff0c;它要求作者不仅要有扎实的专业知识&#xff0c;还要具备高效的信息处理能力和清晰的表达技巧。学术写作是一个复杂的过程&#xff0c;涉及多个阶段&#xff1a;从选题、资料搜集、论文结构设计&#xff0…

STM32(五):定时器——输出比较

定时器输出比较功能&#xff1a;输出PWM波形 OC&#xff08;Output Compare&#xff09;输出比较 输出比较可以通过比较CNT与CCR寄存器值的关系&#xff0c;来对输出电平进行置1、置0或翻转的操作&#xff0c;用于输出一定频率和占空比的PWM波形。 每个高级定时器和通用定时器…

【硬件模块】红外跟随避障模块

红外跟随避障模块实物图 红外避障模块不断发射红外信号&#xff0c;当红外信号&#xff1a; 有反射回来&#xff0c;OUT 输出低电平&#xff0c;输出指示灯&#xff08;绿灯&#xff09;亮&#xff1b; 没反射回来&#xff0c;OUT 输出高电平&#xff0c;输出指示灯&#xff08…

tcp通信以及wireshark抓包

loop: //本地回环测试 tcp在传输时&#xff0c;有可能就会将两次发送的内容粘到一起&#xff0c;这是由于tcp的第三个特点&#xff1a;字节流式传输。它不一定会将两次发送出来的数据进行严格区分。这种现象在tcp链接中叫粘包。 但是socket在底层发送东西的时候是会在一段时间…

【微信小程序】使用 npm 包 - API Promise化-- miniprogram-api-promise

1. 基于回调函数的异步 API 的缺点 默认情况下&#xff0c;小程序官方提供的异步 API 都是基于回调函数实现的&#xff0c;例如&#xff0c;网络请求的 API 需要按照如下的方式调用&#xff1a; 缺点&#xff1a;容易造成回调地狱的问题&#xff0c;代码的可读性、维护性差&a…

I2C软件模拟与Delay寄存器延迟函数

环境 芯片:STM32F103ZET6 库&#xff1a;来自HAL的STM32F1XX.H 原理图 有图可知SCL和SDA两条线接到了PB10和PB11 Driver_I2C.h #ifndef __DRIVER_I2C #define __DRIVER_I2C#include "stm32f1xx.h" #include "Com_Delay.h" // 定义拉高SCL引脚的宏操作 #…

【电子数据取证】应用程序提取及固定

文章关键词&#xff1a;电子数据取证、手机取证、计算机取证、计算机仿真、云取证 一、前言 在数字化时代&#xff0c;电子数据已成为现代社会不可或缺的一部分&#xff0c;它不仅记录着个人的日常生活轨迹&#xff0c;也承载着企业运营的核心信息&#xff0c;更在司法体系中…

Nginx知识详解(理论+实战更易懂)

目录 一、Nginx架构和安装 1.1 Nginx 概述 1.1.1 nginx介绍 1.1.2 Nginx 功能介绍 1.1.3 基础特性 1.1.4 Web 服务相关的功能 1.2 Nginx 架构和进程 1.2.1 Nginx 进程结构 1.2.2 Nginx 进程间通信 1.2.3 Nginx 启动和 HTTP 连接建立 1.2.4 HTTP 处理过程 1.3 Nginx …

pdf转换成excel在线转换?这3款别错过

作为一名财务人员&#xff0c;我每天的工作都离不开处理大量的文件和数据。其中&#xff0c;将PDF格式的报表转换成Excel表格是一项经常要做的工作。在众多的PDF转换工具中&#xff0c;我试过了三款PDF转换工具&#xff0c;现在就来分享一下我的使用体验。 一、福昕PDF转换大师…

普元EOS-低开页面下拉选择控件加载列表数据

1 前言 普元EOS进行低代码开发页面可以高效提高开发效率&#xff0c;并且减少代码的出错机会。 在低代码开发页面的时候&#xff0c;表单页面中可以使用大量的常用控件。 本文将讲解下拉选择组件的使用。 2 下拉选择使用EOS内置字典作为数据源 下拉选择可从字典作为数据源&a…

25届网安秋招面试之后台信息泄露

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s…

C++ TinyWebServer项目总结(9. I/O 复用)

I/O 复用使得程序能够同时监听多个文件描述符&#xff0c;从而提高程序的性能。I/O 复用本身是阻塞的。Linux 下实现 I/O 复用的系统调用主要有 select、poll 和 epoll。 select 系统调用 select API select系统调用&#xff1a;在一段指定时间内&#xff0c;监听用户感兴趣…

Java语言程序设计——篇十七(1)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; 欢迎大家&#xff1a;这里是我的学习笔记、总结知识的地方&#xff0c;喜欢的话请三连&#xff0c;有问题可以私信&#x1f333;&#x1f333;&…