Vue.js。子组件中的变异道具不会触发警告。想知道为啥
Posted
技术标签:
【中文标题】Vue.js。子组件中的变异道具不会触发警告。想知道为啥【英文标题】:Vuejs. Mutating prop in child component does not trigger warning. Wondering whyVue.js。子组件中的变异道具不会触发警告。想知道为什么 【发布时间】:2021-03-10 05:39:20 【问题描述】:我注意到 prop 突变 (Vue 2.6) 有一些奇怪的地方。
应避免直接在子组件中修改 props,否则会触发以下著名警告
"避免直接改变一个 prop,因为它的值是 被覆盖了……”
所以如果在我的父组件中我有一个类似的数据
exemple: "Hello World"
我作为道具传递给子组件。如果在那个子组件中我做类似的事情
this.exemple = "Hello World!"
我收到警告。很公平。现在我注意到如果父级中的数据是像
这样的对象exemple : message : "Hello World"
在孩子身上我会做类似的事情
this.exemple.message = "Hello World!"
这不会触发任何警告,而且父组件中的数据会更新
我想知道为什么。为什么 prop 突变在一种情况下会传播到父级,而在另一种情况下不会传播到父级?它可能与javascript如何存储这些变量有关吗?使用这个技巧是个好习惯吗?
【问题讨论】:
您可以发出更改this.$emit('update:example', 'Hello!')
... 并在父同步中 :example.sync="example"
... 这样 vue 就会知道更改并可以执行任何需要的响应操作
【参考方案1】:
因为突变预防只捕获对道具的直接分配 - 它不会捕获对其属性的操作。这个想法是,如果您为道具分配新值 - 您将分配给prop
,而不是分配给位于提供道具的父 Vue 组件中的变量。
一旦父组件中的某些内容更新了 feed 变量 - prop 将使用这个新值进行更新,并且您分配给子组件中 prop 的值将被覆盖。
如果你给 props 提供一个对象,然后在你的子组件中改变 prop 内的属性 - 它会影响父组件内的同一个对象。但是,如果您尝试为子组件中的 prop 分配一个新对象 - 您应该会收到关于 mutating props 的相同警告。
【讨论】:
【参考方案2】:为什么 prop 突变在一种情况下会传播到父级,而在另一种情况下不会传播?它可能与javascript如何存储这些变量有关吗?
是的。 JavaScript reference 变量(例如对象和数组)在您改变它们的属性/值时不会改变它们的引用。这意味着父级也可以访问更改的属性,因为它也可以访问引用。并且 Vue 只有在引用发生变化时才会给出 prop 突变警告。
警告:
this.prop =
没有警告:
this.prop.id = 5
使用这个技巧是个好习惯吗?
没有。又回到了违反One way data flow 的问题,其中数据通过道具向下传递(到孩子)并通过事件向上传递(到父母)。
好的,但为什么 Vue 不警告这些变化?
考虑一个有 1000 个属性的对象或一个有 1000 个项目的数组。 Vue 必须深入检查所有 1000 个更改,并且没有快速的方法可以做到这一点,因为每个项目都必须单独与旧值进行比较。这会对性能产生影响,并可能使许多应用程序无法使用。
这是来自 Vue 团队成员Bolerodan 的comment:
通常你不应该那样做。这可能/可能会导致代码中出现意外错误。通常,您应该复制您的对象,对其进行修改,然后向上发送到父对象(我相信正如您在上一段中提到的那样)。这是我采用的方法,也是自上而下、自上而下的普遍共识。
【讨论】:
【参考方案3】:一个非常简单的答案是,您正在改变 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
【讨论】:
以上是关于Vue.js。子组件中的变异道具不会触发警告。想知道为啥的主要内容,如果未能解决你的问题,请参考以下文章
当根组件中的值更改时,子组件中的 Vue.js props 值不会更新
Vuex 全局状态更改不会触发 Nuxt 中 v-for 循环中的重新渲染组件