props \ defineProps

vue 官网 Props

  • 命名:如果一个 prop 的名字很长,建议使用小驼峰 props: { greetingMessage: String }
  • 使用:
  1. 使用时为了和 HTML attribute 对齐,通常将其写为 短横线 形式 <MyComponent greeting-message="hello" />

  2. 有时虽为常量但也要使用 v-bind,因为这是一个 JavaScript 表达式而不是一个字符串

<BlogPost :likes="42" /> /* 42 为数字,不为字符串 */
<BlogPost :likes="false" /> /* false 为布尔值,不为字符串 */
<BlogPost is-published /> /* 仅写上 prop 但不传值,会隐式转换为 `true` */
如果没有在 props 中把 is-published 的类型设置为 Boolean,则这里的值为空字符串,而不是“true”。
  1. 只使用 v-bind 而非 :prop-name
// data() 中定义
post: {
	id: 1,
	title: 'My Journey with Vue'
}

<BlogPost v-bind="post" />
// 等价于
<BlogPost :id="post.id" :title="post.title" />
  • 单项数据流:父级 prop 的更新会向下流动到子组件中, 不应该在一个子组件内部改变 prop

1 props

一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute

  • <template> 中引用: propA
  • <script> 中引用: this.propsA
// 1. 字符串数组
props: ['foo']

// 2. 对象
prop: {
	title: String,  // title 为名称,String 为构造函数
	likes: Number
}

// 3. 可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。
prop: {
	// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
	propA: Number,
	// 多个可能的类型
	propB: [String, Number],
	// 必填的字符串
	propC: {
	  type: String,
	  required: true,
	},
	// 带有默认值的数字
	propD: {
	  type: Number,
	  default: 100,
	},
	// 带有默认值的对象
	propE: {
	  type: Object,
	  // 对象或数组默认值必须从一个工厂函数获取
	  default: function () {
		return { message: "hello" };
	  },
	},
	propE: { 
	  type: Object, 
	  default: () => {} 
	},
	propE: {
	  type: Array,
	  default() {
	    return [];
	  }
	},
	// 自定义验证函数
	propF: {
	  validator: function (value) {
		// 这个值必须匹配下列字符串中的一个
		return ["success", "warning", "danger"].indexOf(value) !== -1;
	  },
	},
}
  • type 可以是原生构造器:String、Number、Boolean、Array、Object、Date、Function、Symbol
  • type 也可以是一个自定义构造器,使用 instanceof 检测。

2 defineProps

只能在 <script setup> 中使用,无需导入

defineProps API 接收与 props 选项相同的值

  • <template> 中引用: propA
  • <script> 中引用: props.propsA
// 仅<template> 中使用 propA、propB
defineProps({
  propA: { type: [Number, String], default: '' },
  propB: { type: Number, default: 2 }
});

// <script> 中也使用 propA、propB, 声明为变量
const props = defineProps({
  propA: { type: [Number, String], default: '' },
  propB: { type: Number, default: 2 }
});
  • 因为 defineProps 只是一个语法糖,并不是一个真实存在的函数,它的作用在于告诉 vue 运行时工具,这里我们要引入一个变量。所以不能用普通变量的方式去看待它。
  • 用于组件通信中父级组件给子级组件传值,其用来声明 props,其接收值为props选项相同的值
  • 默认支持常见的类型检查,在 ts 下,我们需要明确变量的类型,类型经常是我们的自定义类型
  • 只能在 <script setup> 中使用
  • 不需要被导入即可使用,它会在编译 <script setup> 语法块时一同编译掉
  • 必须在 <script setup> 的顶层使用,不可以在 <script setup> 的局部变量中引用
  • 不可以访问 <script setup> 中定义的其他变量,因为在编译时整个表达式都会被移到外部的函数中
  • defineProps 是 props 从选项式 API 到组合式 API 的变体

理解 Vue3 里的 defineProps 和 defineEmits
vue3实战中关于 props 的一个细节问题

  • 最初的 Composition API 是在 Options API 基础上改进的,不仅需要使用 setup() 函数,还要在 setup() 末尾返回所有模版需要用到的变量和函数,使用起来相当繁琐。于是后面就增加了 <script setup> 语法糖:
  • 从生命周期来讲,相当于 created
  • 支持顶层 await(因为实际上这还是个 setup() 函数)
  • 所有 import 的内容、声明的变量和函数默认都返回
  • 至少省了两层缩进
  • 但是由于少了 export,没法传参,也不方便暴露接口,所以作者就增加了三个工具方法:defineProps、defineEmits、defineExpose
  • 注意,这三个工具方法只是帮助 Vue 编译器构建组件,它们不会出现在最终代码里,我们也不能预期它们会像普通函数那样工作。
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐