百科狗-知识改变命运!
--

props 数据 - 父组件向子组件单向传递数据 - vue 组件

是丫丫呀1年前 (2023-11-21)阅读数 20#技术干货
文章标签组件

props 数据

Props 声明

组件需要显式声明props,这样 Vue 才能知道,外部传入的,哪些是props,哪些是透传attribute(下一章中我们会讨论到它)。

在单文件组件中使用

{{ foo }]

在没有使用

{{ foo }]

请注意,传给defineProps()的参数和提供给props 选项的值是相同的,两种声明方式背后其实使用的都是props 选项

除了使用字符串数组来声明props外,还可以使用对象的形式:

对于以对象形式声明中的每个属性,key是 prop 的名称,而值应该是预期类型的构造函数。比如,如果要求一个 prop 的值是number类型,则可使用Number构造函数作为其声明的值。

对象形式的 props 声明不仅可以一定程度上作为组件的文档,而且如果其他开发者在使用你的组件时传递了错误的类型,也会在浏览器控制台中抛出警告。


如果你正在搭配 TypeScript 使用


props 传值

prop 名字格式

如果 prop 的名字很长,应使用camelCase形式,因为它们是合法的 JavaScript 标识符,可以直接在模板的表达式中引用。避免在作为属性 key 名时必须带引号。

js
defineProps({
  greetingMessage: String
})
template
{{ greetingMessage }}

从技术上来讲,你也可以在向子组件传递props时使用camelCase形式。(使用 DOM 模板时例外)而实际上为了和 HTML attribute 对齐,都会将其转为kebab-case形式:

template 

一般情况下都会使用PascalCase作为组件标签名,因为这提高了模板的可读性,能很好地区分出 Vue 组件和原生 HTML 元素。然而这对于传递 props 来说收效却并不高,因此我们选择对其进行转换。


静态 vs.动态 Props

至此,你已经见过了很多像这样的静态值形式的 props:

相应地还有使用v-bind或缩写:所动态绑定的 props 值:


props 传值类型

在上述两个示例中,我们传入的值都是字符串类型的,但实际上任何类型的值都可以传给一个 prop。

Number


Boolean


Array


Object


传入一个对象的所有 property

如果你想要将一个对象的所有 property 都作为 prop 传入,你可以使用不带参数的v-bind,而非:prop-name。例如,对于一个给定的对象post

post: {
  id: 1,
  title: 'My Journey with Vue'
}

下面的模板:

等价于: 


单向数据流

所有的 prop 都遵循着单向下行绑定原则,prop 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改了父组件的状态,不然应用的数据流就会变得难以理解了

另外,每次父组件更新后,所有的子组件中的props都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop。若你这么做了,Vue 会在控制台上向你抛出警告:

const props = defineProps(['foo'])

//  警告!prop 是只读的!
props.foo = 'bar'

想要更改 prop 通常都符合以下两种场景:

1、prop 用来传递一个初始值;而子组件想在之后希望将其作为一个本地局部的数据来使用。在这种情况下,最好是新定义一个局部数据属性,从props上取初始值即可:

const props = defineProps(['initialCounter'])

// 计数器只是将 props.initialCounter 作为初始值
// 像下面这样做就使 prop 和后续更新无关了
const counter = ref(props.initialCounter)

2、prop 以一种原始的值传入,但还需作转换。在这种情况中,最好是基于该 prop 值定义一个计算属性:

const props = defineProps(['size'])

// 该 prop 变更时计算属性也会自动更新
const normalizedSize = computed(() => props.size.trim().toLowerCase())


更改对象/数组类型的 prop

当对象或数组作为 prop 被传入时,虽然子组件无法更改 prop 绑定,但仍然可以更改对象或数组内部的值。这是因为 JavaScript 的对象和数组是按引用传递,而对 Vue 来说,禁止这样的改变。不虽然可能,但有很大的性能损耗,比较得不偿失。

这种更改的主要缺陷是它允许了子组件以某种不明显的方式影响了父组件的状态,可能会使数据流在将来变得更难以推理。在最佳实践中,你应该尽可能避免这样的更改,除非父子组件在设计上本来就需要紧密耦合。在大多数场景下,子组件应该抛出一个事件来通知父组件做出改变。


prop 校验

Vue 组件可以更细致地声明对传入的 props 的校验要求。比如我们上面已经看到过的类型声明,如果传入的值不满足类型要求,Vue 会在浏览器控制台中抛出警告来提醒使用者。这在开发给其他开发者使用的组件时非常有用。

要描述对 prop 的校验,你可以向defineProps()宏提供一个带有 prop 校验的对象,而不是一个字符串数组,例如:

defineProps({
  // 基础类型检查
  // (给出 `null` 和 `undefined` 值则会跳过任何类型检查)
  propA: Number,

  // 多种可能的类型
  propB: [String, Number],

  // 必传,且为 String 类型
  propC: {
    type: String,
    required: true
  },

  // Number 类型的默认值
  propD: {
    type: Number,
    default: 100
  },

  // 对象类型的默认值
  propE: {
    type: Object,
    // 一个返回默认 对象/数组值 的工厂函数
    default() {
      return { message: 'hello' }
    }
  },

  // 自定义类型校验函数
  propF: {
    validator(value) {
      // The value must match one of these strings
      return ['success', 'warning', 'danger'].includes(value)
    }
  },

  // 函数类型的默认值
  propG: {
    type: Function,
    // 不像对象或数组的默认,这不是一个工厂函数。这会是一个用来作为默认值的函数
    default() {
      return 'Default function'
    }
  }
})
defineProps()宏中的参数不可以访问中定义的其他变量,因为在编译时整个表达式都会被移到外部的函数中。

一些补充细节:

  • 所有 props 默认都是可选的,除非声明了required: true
  • 未传递的 prop 会有一个缺省值undefined
  • 如果声明了default值,那么在 prop 的值被解析为undefined时,无论 prop 是未被传递还是显式指明的undefined,都会改为default值。

当 prop 的校验失败后,Vue 会抛出一个控制台警告(在开发模式下)。

如果使用了基于类型的 prop 声明,Vue 会尽最大努力在运行时按照 prop 的类型标注进行编译。举个例子,defineProps会被编译为{msg:{type: String, required: true}}


类型检查

type可以是下列原生构造函数中的一个:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

此外,type还可以是一个自定义的构造函数,并且通过instanceof来检查、断言。例如下面这个类:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }
}

你可以将其作为一个 prop 的类型:

defineProps({
  author: Person
})

这会校验author prop 的值是否是由new Person创建的。


Boolean 类型转换

为了更贴近原生Boolean attributes 的行为,声明为Boolean类型的 props 有特别的类型转换规则。以带有如下声明的组件为例:

defineProps({
  disabled: Boolean
})

该组件可以被这样使用:

当需要一个 prop 在声明时允许多种类型时,应该像这样:

defineProps({
  disabled: [Boolean, Number]
})

props 数据 - 父组件向子组件单向传递数据 - vue 组件

无论声明类型的顺序如何,Boolean类型的特殊转换规则都会被应用。

鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com

免责声明:我们致力于保护作者版权,注重分享,当前被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!邮箱:344225443@qq.com)

图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

内容声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。部分内容参考包括:(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供参考使用,不准确地方联系删除处理!本站为非盈利性质站点,本着为中国教育事业出一份力,发布内容不收取任何费用也不接任何广告!)