写点什么

在 Vue 中,为什么从 props 中解构变量之后再 watch 它,无法检测到它的变化?

作者:Lee Chen
  • 2023-04-08
    福建
  • 本文字数:1347 字

    阅读完需:约 4 分钟

  1. 例如下面这段代码,msg 无法被 watch


import { watch } from 'vue';
export default { props: { msg: String }, setup(props) { // 从 props 中解构 msg const { msg } = props;
watch( () => msg, (newVal, oldVal) => { console.log('newVal', newVal); console.log('oldVal', oldVal); } );
return {}; }};
复制代码


原因如下:


当您从 props 对象中解构 msg 时,msg 变量将会获取到当时的 props.msg 值。解构操作仅仅是将当前值复制到 msg 变量中,它并不会建立响应式连接。因此,当 props.msg 发生变化时,解构出的 msg 变量仍保持其原始值,不会自动更新。


在这种情况下,如果您尝试使用 watch 观察 msg 变量,将无法检测到 props.msg 的变化。这是因为 msg 变量在 setup 函数作用域内始终保持不变。


要正确观察 props.msg 的变化,您应该将 props 作为参数传递给 watch 函数的依赖项函数,而不是解构后的 msg 变量。这样,watch 函数将始终能获取到 props.msg 的最新值。示例:


watch(  () => props.msg,  (newVal, oldVal) => {    console.log('newVal', newVal);    console.log('oldVal', oldVal);  });
复制代码


  1. 这和 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 无法检测到它的变化。


  1. “shallowReactive 函数会创建一个浅响应式的代理”是什么意思?


shallowReactive 函数用于创建一个浅响应式的代理对象。它是 Vue 3 提供的一个响应式 API。当使用 shallowReactive 函数包装一个对象时,它会返回一个代理对象,该代理对象的顶层属性会变为响应式的。换句话说,只有第一层属性会变为响应式,而嵌套的对象或数组则保持原样,不会变为响应式。


以下是一个简单的示例:


import { shallowReactive } from 'vue';
const obj = { a: 1, b: { c: 2 }};
const reactiveObj = shallowReactive(obj);
复制代码


在这个示例中,obj 是一个包含两个属性 ab 的普通对象。使用 shallowReactive 函数将 obj 包装为一个浅响应式代理对象(reactiveObj)。在这个代理对象中,ab 属性变为响应式的,但是 b 属性内部的 c 属性保持非响应式。


当您访问或修改 reactiveObjab 属性时,Vue 能够跟踪这些变化并触发相应的更新。然而,对于嵌套的属性,如 reactiveObj.b.c,Vue 无法检测到其变化,因为它没有变为响应式。


shallowReactive 函数在某些情况下很有用,例如当您不需要对整个嵌套结构进行响应式处理时,可以通过使用浅响应式代理来提高性能。

发布于: 刚刚阅读数: 2
用户头像

Lee Chen

关注

还未添加个人签名 2018-08-29 加入

还未添加个人简介

评论

发布
暂无评论
在Vue中,为什么从 props 中解构变量之后再watch它,无法检测到它的变化?_JavaScript_Lee Chen_InfoQ写作社区