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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值