大家好,这里是大家的林语冰。今天分享的是 Vue 官方周报安利的一篇博客。
免责声明
本文属于是语冰的直男翻译了属于是,仅供粉丝参考,英文原味版请临幸 Vue.js Patterns: Using Vue.js 3 Composition API for Reactive Parent to Child Communication。
不同于 React,Vue 围绕响应式系统做"圆周运动"。在本文中,我们将探讨如何使用 Vue 3 组合式 API 创建响应式父子通信。
用例如下:父组件需要将数据传递给子组件。祂使用 Props
实现。子组件需要接收这个外部数据作为其初始状态,但也能在内部变更祂,举个栗子:文本输入元素的双向数据绑定。
我们在实现时面临的限制如下:
prop
被设计为不可变属性。子组件不该改变祂从父组件接收的数据。Ref
是可变数据,且允许您设置初始数据,比如const content = ref(props.content)
,但最终可能是一个坑,这取决于您如何使用它们。
Ref 有什么问题?
Ref 是 Vue 响应式系统的一部分。祂们用于创建响应式数据,并且是 Vue 3 组合式 API 妥当的构建区块。
虽然但是,根据我见过的大多数指南,可能您使用祂们的方式对于已定义用例没有帮助。
请考虑下列父组件的代码:
在子组件中,您可能会考虑将 ref 绑定到源自父组件的 props 初始值,以此来使用 ref,如下所示:
这是一段合法的代码,并且就技术而言可以奏效,但是您必须了解 Vue 的生命周期 hook 才能理解为什么这绝非最佳实践。
在此组件的 setup
手法中,ref()
当且仅当组件挂载时会调用一次。这意味着,如果父组件更改 content
prop,子组件无法得知该更改。
Ref 的正确打开方式是什么?watch 来援救!
此问题的解决方案是使用 watch()
函数或其更智能的同胞函数:watchEffect()
。类似于 Ref,watch
函数是 Vue 响应式系统的一部分,且允许您监测更改响应式对象的变化,而不用顾虑组件的生命周期 hook。
以下是完整的代码示例。
我们将表演如何将默认初始值从父组件传递到子组件,并将其设置为使用 Vuetify 3 和 Vue 组合式 API 的值,同时启动双向绑定。
父组件定义如下,附带传递给子组件的 content
prop,且该属性可能被父组件根据其自身状态动态更改:
在子组件中,我们会定义一个文本输入元素,该元素使用 Vue 的 v-model
指令绑定到一个内容引用。这将允许我们更改子组件中 content
ref 的值,实现我们想要的双向绑定。
这也允许父组件更改 content
prop 的值,这将反映在子组件中。
为了让子组件知道传递给祂的 props 的变化,我们会使用 watchEffect()
函数来监测 content
prop 的变化。这将允许我们更新 content
ref 的值,该值会反映在子组件中。
将以下代码添加到全局作用域中子组件的 content
变量定义旁边:
让我们解释一下此处 watch()
函数的行为。
您在此处看到的 watch
函数是 Vue 组合式 API 的一部分。其目的是观察特定响应源的变化并做出反应。祂可以是简单的响应式引用(比如 ref
),也可以是返回响应源的函数。
祂的工作机制如下:
() => props.content
:这叫做"源"函数。祂应该返回您想监测的值。在本例中,祂是从 props 传递过来的content
值。() => { content.value = props.content }
:这是源更改时执行的回调函数。在本例中,祂将props.content
的值赋值给content
ref。
您还可以传递额外的第三个参数选项对象,比如 { immediate: true }
,这意味着回调应该在创建 watch
之后立即运行,甚至在源更改之前。对于在设置 watch
时您希望初始运行回调的情况,这很有用。
我们可以使用更精简的 watchEffect()
函数来代替,也能达到相同的结果。每次 content
prop 水合(hydrate)时都会调用 watchEffect()
函数,并更新 content
ref 的值,这将反映在子组件中。
粉丝福利:脱离 setup
语法糖使用此模式
这是对上述内容的通用重写,但不使用 setup
脚本手法,用于演示如何使用 Vue 3 组合式 API 来实现我们的用例:
在这个例子中,initialData
是父组件传递过来的 prop。响应式变量 data
是 initialData
的局部拷贝。watchEffect
函数用于在 initialData
更改时更新 data
,确保 data
始终以 initialData
的当前值开始。
由于 data
是局部拷贝,因此祂可以在子组件内自由变更,而不会影响父组件中 prop 的值。
您现在收看的是直男翻译系列,学废了的小伙伴可以点赞友情赞助本系列,我们每天佛系投稿,欢迎关注和订阅最新动态。谢谢大家的彼芯,掰掰~