在玩Vue 3 Reactive时,我出现了一种我无法解释的行为.

我创造了一个原始人的ref.在上面判断isRef,显然返回true.但是当作为propisRef()isReactive()传递给子组件时,返回false.为什么?

此外,即使它们都返回false,如果值发生更改,我在子组件中添加的这个props 的观察器也会被触发.如果观察值既不是ref也不是reactive,它怎么会触发呢?

下面是父进程和子进程的代码片段:

父级.查看

let foo = ref(0);
function changeFoo() {
  foo.value++;
}
  
console.log("parent check is reactive?", isReactive(foo)); // retruns false
console.log("parent check is ref?", isRef(foo)); // retruns true

watch(foo, (value, oldValue) => {
  console.log("foo changing from", oldValue, "to ", value);
});

Child.vue

const props = defineProps<{
  foo: number;
}>();

console.log("child check is reactive?",isReactive(props), isReactive(props.foo)); // returns true false
console.log("child check is ref ?",isRef(props), isRef(props.foo)); // returns false false // Question 1: Why props.foo is not a Ref ?
  
watch(props, (value, oldValue) => {
  console.log("props changing from", oldValue, " to ", value);
});
 
watch(()=>props.foo, (value, oldValue) => {
  // Question 2: Why this Watcher detects changes of "foo" without it being a ref nor reactive ?
  console.log("props.foo changing from ", oldValue, " to ", value);
});

和Vue SFCplayground here的链接

prize 问题: 当foo被传递给子组件中使用的Composable时,除非我们通过toRef传递foo,否则Composable内的观察器不会被触发,但如果foo是一个ref/active对象,则不需要这个额外的步骤.为什么原语需要这个加法步骤?

推荐答案

但是,当作为props 传递给子组件时,isRef()和isReactive()也返回FALSE.

正如你自己的 comments 所表明的那样,你在这里只讲述了故事的一半:

console.log("child check is reactive?",isReactive(props), isReactive(props.foo)); // returns true false

isReactive(props) does返回TRUE,因为整个props对象(包装foo)是react 性的.父对象对foo所做的任何更新都将作为更新的props对象传递给子对象.props.foo确实不是一个裁判/react ,因为它不需要是.只要props是被动的,props.foo就会更新

观察器能够在更改到props.foo时激活,因为您实际上使用了特殊的语法,其中您将一个"getter"传递给专门用于监视property of a reactive object的手表(在您的例子中是:props ).在Vue docs人中有一个例子也表达了同样的观点.

如果您需要将props.foo赋给它自己的react 变量,比如传递给可组合变量,这就是toRef可以使用的地方.

// reactive but not synced with props.foo
const newFoo = ref(props.foo)

// reactive AND synced with props.foo
const newFoo = toRef(props, 'foo')

正如我在上面的注释中指出的,如果您只用ref创建一个新变量,它将是react 性的,但它不会与它的源属性同步,即第一个newFoo不会在props.foo个更新时进行react 性更新,但第二个newFoo会.这一点在Vue docs中也得到了很好的解释

Vue.js相关问答推荐

具有VUE身份验证的Azure AD

当用户在嵌套路由中时激活链接

Vuejs - 更新数组中对象的数组

在组件之间共享 websocket 连接

将 Vue 应用程序挂载到主 Vue 应用程序的容器中

Vuex store 在 Nuxt 的什么地方

Vue-router:循环路由以动态创建

Webpack 你可能需要一个合适的加载器来处理这个文件类型

VueJS:向左,元素的顶部位置?

包含 Vue.js v-if 和 v-for 指令的 HTML 标签在加载时flash

webpack模块解析失败意外字符'@'

Vue:从 Vue 实例更新组件数据

命名空间模块身份验证的重复命名空间身份验证

Vuetify v-btn 路由活动类问题

为什么 v-model 不适用于数组和 v-for 循环?

删除一行后刷新 Bootstrap-Vue 表

vue-cli-service build --target lib 导入为 lib 时丢失图像路径

如何从组件内的单点捕获 vuejs 错误

为什么不能在 vue 模板中使用窗口?

如何在 vue 组件中使用 vuex?