Vuejs。 child 组件中的 mutating prop 不会触发警告。想知道为什么

Vuejs. Mutating prop in child component does not trigger warning. Wondering why

我注意到 prop 突变有些奇怪(Vue 2.6)。

应避免直接在 child 组件中修改 props,否则会触发以下著名警告

"Avoid mutating a prop directly since the value will be overwritten...."

因此,如果在我的 parent 组件中,我有一个类似

的数据
exemple: "Hello World"

我作为道具传递给 child 组件。如果在那个 child 组件中我做了类似

的事情
this.exemple = "Hello World!"

我收到警告。很公平。现在我注意到,如果 parent 中的数据是 object 之类的

exemple : {message : "Hello World"}

并且在 child 我做了类似的事情

this.exemple.message = "Hello World!"

这不会触发任何警告,而且 parent 组件中的数据得到更新

我想知道为什么。为什么 prop 突变在一种情况下会传播到 parent 而在另一种情况下不会传播?它可能与 javascript 存储这些变量的方式有关吗?使用这个技巧是好习惯吗?

因为突变预防只捕获对 prop 的直接赋值 - 它不捕获对其属性的操作。这个想法是,如果您为 prop 分配新值 - 您将分配给 prop 而不是位于为 prop 提供数据的父 Vue 组件中的变量。

一旦父组件中的某些内容更新了 feeding 变量 - prop 将更新为这个新值,并且您在子组件中分配给 prop 的值将被覆盖。

如果您将对象提供给 prop,然后在子组件的 prop 内改变 属性 - 它会影响父组件内的同一对象。但是,如果您尝试将一个新对象分配给子组件中的 prop - 您应该会收到关于 mutating props 的相同警告。

Why does the prop mutation propagate to the parent in one case but not in the other ? Does it have maybe something to do with how javascript stores these variable ?

是的。 JavaScript reference 变量(例如 object 和数组)在您改变它们的 properties/values 时不会更改它们的引用。这意味着 parent 也可以访问更改的属性,因为它也可以访问引用。如果引用发生变化,Vue 只会给出 prop 突变警告。

警告:

this.prop = {}

无警告:

this.prop.id = 5

Is it good practice to use that trick ?

没有。它又回到了违反 One way data flow 的地方,其中数据通过道具向下传递(到 child)并通过事件向上传递(到 parent)。


好的,但为什么 Vue 不对这些更改发出警告?

考虑具有 1000 个属性的 object 或具有 1000 个项目的数组。 Vue 必须深入检查所有 1000 个更改,并且没有快速的方法可以做到这一点,因为每个项目都必须单独与旧值进行比较。这会对性能产生影响,并可能使许多应用程序无法使用。


这是 Vue 团队成员 Bolerodan 关于这个主题的 comment

Generally you shouldnt do that. This can / could cause unexpected bugs in your code. Generally you should make a copy of your object, modify that, then emit upwards to the parent (as you have mentioned in your last paragraph I believe). This is the method I take and is the general consensus of top down, emit up approach.

一个非常简单的答案是你正在改变一个 reference value 并且 Vue 不跟踪整个 reference 而它只检查引用所在的地址。因此,如果您重新分配该值,那么它会警告您。

理解行为的一个很好的例子是通过变量声明来理解const

const 使您的变量不可变,但如果值本质上是 primitive,则同样适用于它,您无法更改它,但如果它是 reference,则您可以'不要更改它,但您绝对可以更新位于 reference

的值

const a = 'Foo' // Primitive value

a = 'bar' // voilation
 
const b = { // Reference value
 name: 'Foo' 
}

b.name = 'Bar' // It's good

console.log(b)

b = {} // re-assign is voilation