跳至主要内容

属性 (Props)

什么是属性?

Props 指的是从父组件传递下来的数值。这些数值会被存放在一个通常叫做 props 的物件中。

举例来说,若您在子组件中这样宣告 props:

ChildComponent.vue
const props = defineProps<{
name: string
age: number
}>()

那么在父组件您就能这样把数值传递下去:

ParentComponent.vue
<template>
<ChildComponent
:name="myName"
:age="myAge"
/>
</template>

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

const myName = ref('hello')
const myAge = ref(5)
</script>

浅层响应 (Shallow Reactive) 和浅层唯读 (Shallow Readonly)

这里有个有趣的知识:props 物件其实是一个有着浅层唯读限制的非严格浅响应代理 (non-strict shallow reactive proxy)!

什么是浅层响应 (Shallow Reactive)?

浅层响应指的是在一个物件中,只有顶层属性具有响应性;所有非顶层属性都不具有响应性。我们可以使用 shallowReactive() 函数来宣告一个浅响应代理,例如:

import { shallowReactive } from 'vue'

const user = shallowReactive({
name: 'hello',
child: {
age: 5,
},
})

在这个范例中,user 被宣告为一个浅响应代理,这意味着:

  • 修改 user.name 的值会导致组件重新渲染。
  • user.child 取代成其他任意数值会导致组件重新渲染。
  • 修改 user.child.age 不会导致组件重新渲染。

然而,如果 user.child 在一开始就已经是响应式代理,那么修改 user.child.age 也会造成组件重新渲染;因为 shallowReactive() 能做的只有赋予响应性给顶层属性,他从来不会「去除响应性」,例如:

import { reactive, shallowReactive } from 'vue'

const user = shallowReactive({
name: 'hello',
child: reactive({
age: 5,
}),
})

在这个范例中:

  • 修改 user.name 会导致组件重新渲染,因为 user 是一个浅响应代理。
  • user.child 取代成其他任意数值会导致组件重新渲染,因为 user 是一个浅响应代理。
  • 修改 user.child.age 也会导致组件重新渲染,因为 user.child 是一个响应式代理。
信息

reactive() 不同,shallowReactive() 在建立代理的过程中不会经过解包的过程,所以 shallowReactive() 的返回型别必定会和传入的参数型别相同。

什么是浅层唯读 (Shallow Readonly)?

浅层唯读指的是在一个物件中,只有顶层属性具有唯读的限制;所有非顶层属性都不具有唯读的限制。我们可以使用 shallowReadonly() 函数来建立一个浅层唯读物件,例如:

import { shallowReadonly } from 'vue'

const user = shallowReadonly({
name: 'hello',
child: {
age: 5,
},
})

在这个范例中,user 被宣告为一个浅层唯读物件,这意味着:

  • 我们无法修改 user.name
  • 我们无法将 user.child 取代为其他数值。
  • 我们可以修改 user.child.age

总结一下,您可以将 props 想像成是一个使用 shallowReactive()shallowReadonly() 宣告出来的浅响应代理;只不过所有的属性值都是由父组件传递下来的。

import { shallowReactive, shallowReadonly } from 'vue'

const props =
shallowReadonly(
shallowReactive({
// ...
})
)
信息

您应该极力避免从子组件直接修改 props,如此一来才能维持单向资料流 (从上方流向下方)。若您的子组件需要修改 props 的数值,您应该使用自定义事件 (events)。主要的概念是,只有父组件才被允许修改 props 的数值,子组件做的只是「触发」那些做出改变的事件而已。

Props 的响应性

您是否曾经遇过出于某种原因,「某些」props 中的属性就是不具有响应性

在大多数情况下,这意味着您不小心破坏了 props 的响应性。由于 props 物件是一个浅响应代理,您可以把它当成是响应式代理来处理。看看这里提到的解决方法!