在 Vue 中,为什么从 props 中解构变量之后再 watch 它,无法检测到它的变化?
例如下面这段代码,msg 无法被 watch
原因如下:
当您从 props
对象中解构 msg
时,msg
变量将会获取到当时的 props.msg
值。解构操作仅仅是将当前值复制到 msg
变量中,它并不会建立响应式连接。因此,当 props.msg
发生变化时,解构出的 msg
变量仍保持其原始值,不会自动更新。
在这种情况下,如果您尝试使用 watch
观察 msg
变量,将无法检测到 props.msg
的变化。这是因为 msg
变量在 setup
函数作用域内始终保持不变。
要正确观察 props.msg
的变化,您应该将 props
作为参数传递给 watch
函数的依赖项函数,而不是解构后的 msg
变量。这样,watch
函数将始终能获取到 props.msg
的最新值。示例:
这和 Vue 源码中
packages/runtime-core/src/componentProps.ts
这个文件里面的instance.props = isSSR ? props : shallowReactive(props)
有关系吗?
是的,这和 Vue 源码中 packages/runtime-core/src/componentProps.ts
文件里的 instance.props = isSSR ? props : shallowReactive(props)
有关系。
这段代码表示,在非服务器端渲染(SSR)的情况下,组件实例的 props
会被包装为浅响应式对象。shallowReactive
函数会创建一个浅响应式的代理,使得在访问或修改 props
对象时,Vue 能够跟踪变化并触发相应的更新。
当您直接在 watch
函数的依赖项函数中访问 props.msg
时,您实际上是访问了一个响应式代理,这使得 Vue 能够检测到 props.msg
的变化。但是,当您从 props
中解构 msg
时,您实际上是访问了原始值。这个值是非响应式的,因此 Vue 无法检测到它的变化。
“shallowReactive 函数会创建一个浅响应式的代理”是什么意思?
shallowReactive
函数用于创建一个浅响应式的代理对象。它是 Vue 3 提供的一个响应式 API。当使用 shallowReactive
函数包装一个对象时,它会返回一个代理对象,该代理对象的顶层属性会变为响应式的。换句话说,只有第一层属性会变为响应式,而嵌套的对象或数组则保持原样,不会变为响应式。
以下是一个简单的示例:
在这个示例中,obj
是一个包含两个属性 a
和 b
的普通对象。使用 shallowReactive
函数将 obj
包装为一个浅响应式代理对象(reactiveObj
)。在这个代理对象中,a
和 b
属性变为响应式的,但是 b
属性内部的 c
属性保持非响应式。
当您访问或修改 reactiveObj
的 a
或 b
属性时,Vue 能够跟踪这些变化并触发相应的更新。然而,对于嵌套的属性,如 reactiveObj.b.c
,Vue 无法检测到其变化,因为它没有变为响应式。
shallowReactive
函数在某些情况下很有用,例如当您不需要对整个嵌套结构进行响应式处理时,可以通过使用浅响应式代理来提高性能。
版权声明: 本文为 InfoQ 作者【Lee Chen】的原创文章。
原文链接:【http://xie.infoq.cn/article/40a973d990544d9fdae039cae】。文章转载请联系作者。
评论