Javascript vue-$emit vs.用于更新父数据的参考

Javascript vue-$emit vs.用于更新父数据的参考,javascript,vue.js,Javascript,Vue.js,我们需要使用$emit更新vue组件中的父数据。这是到处都在说的,甚至是vue文档 v-model和.sync都使用$emit进行更新,所以我们在这里计算它们$emit 我所涉及的是使用reference类型传递更新父数据 如果我们将一个对象或数组作为道具发送给子组件,并在子组件中更改它,则会直接更改父数据 有些组件我们总是在特定组件中使用,我们不会在其他任何地方使用它们。事实上,这些组件主要用于提高应用程序代码的可读性和减轻应用程序组件的负担 将引用类型值作为道具传递给子级,以便直接从子级更改

我们需要使用
$emit
更新vue组件中的父数据。这是到处都在说的,甚至是vue文档

v-model
.sync
都使用
$emit
进行更新,所以我们在这里计算它们
$emit

我所涉及的是使用
reference
类型传递更新父数据

如果我们将一个对象或数组作为道具发送给子组件,并在子组件中更改它,则会直接更改父数据

有些组件我们总是在特定组件中使用,我们不会在其他任何地方使用它们。事实上,这些组件主要用于提高应用程序代码的可读性和减轻应用程序组件的负担

将引用类型值作为道具传递给子级,以便直接从子级更改它们,这比传递值然后处理发出的事件要容易得多。尤其是当有更多嵌套组件时

当我们使用引用类型更新父类时,代码可读性更容易

例如,假设我们有
grandparent
parent
child
组件。在
父级
组件中,我们有一个字段更改了父级数据的
第一个
属性,在子组件中,我们有另一个字段更改了父级数据的
第二个
属性

如果我们想使用
$emit
来实现这一点,我们可以这样做:(我们不使用.sync或v-model)

//祖父母
从“/parent”导入父项
导出默认值{
组件:{parent},
数据(){
返回{
字段:{
第一:“第一个值”,
第二:“第二个值”,
}
}
}
}
//母公司
从“/child”导入子项
导出默认值{
组件:{child},
道具:{
字段:对象,
},
方法:{
updateFirstField(事件){
this.$emit('updateFields',{…this.fields,第一个:event.target.value})
},
updateSecondField(值){
this.$emit('updateFields',{…this.fields,第二个:value})
}
}
}
//孩子
导出默认值{
道具:{
字段:对象,
},
方法:{
updateFirstField(事件){
此.emit('updateSecondField',event.target.value)
},
}
}
是的,我们可以使用
.sync
使其更简单,或者只传递需要生成的字段。但这是一个基本的例子,如果我们有更多的字段,并且我们在所有组件中使用所有字段,我们就是这样做的

使用引用类型的情况与此相同:

//祖父母
从“/parent”导入父项
导出默认值{
组件:{parent},
数据(){
返回{
字段:{
第一:“第一个值”,
第二:“第二个值”,
}
}
}
}
//母公司
从“/child”导入子项
导出默认值{
组件:{child},
道具:{
字段:对象,
}
}
//孩子
导出默认值{
道具:{
字段:对象,
}
}
正如您所看到的,使用
reference
类型要容易得多。即使有更多的领域

现在我的问题是:

  • 我们应该使用引用类型更新父数据,还是这是一种糟糕的方法
  • 即使我们再次在同一父级中使用组件,我们也不应该使用此方法
  • 我们不应该使用
    reference
    type更新父项的原因是什么
  • 如果我们不应该使用
    reference
    type,为什么vue会将同一对象传递给子对象,而不在传递之前克隆它们?(也许是为了更好的表现?)
始终使用
$emit
“规则不是一成不变的。这两种方法各有利弊;您应该尽一切努力使代码易于维护和推理

对于您描述的情况,我认为您有理由直接修改数据

当您有一个具有许多属性的单个对象,并且每个属性都可以由子组件修改时,让子组件对每个属性本身进行变异就可以了

另一种选择是什么?是否为每个属性更新发出事件?或者发出一个
输入
事件,该事件包含一个对象的副本,且单个属性已更改?这种方法会导致大量内存分配(比如在文本字段中键入,每个按键都会发出一个克隆对象)。尽管如此,一些库的设计正是为了这个目的,并且工作得很好(比如)

对于只管理小数据的简单组件,如具有单个字符串值的文本框,您肯定应该使用
$emit
。对于具有大量数据的更复杂组件,有时子组件共享或拥有给定的数据是有意义的。它成为子组件契约的一部分,它将在某些情况下以某种特定的方式对数据进行变异

我们不应该使用引用类型更新父对象的原因是什么

  • 父级“拥有”数据,它知道只有它自己才会对其进行变异。没有意外
  • 父母可以决定是否接受变异,甚至可以动态修改变异
  • 您不需要观察者来知道数据何时更改
  • 父级知道数据是如何更改的,以及更改的原因。想象一下,有多种方式可以改变数据。父代可以很容易地知道哪个突变起源于子代成分。如果外部代码(即子组件内部)可以在任何时候出于任何原因对数据进行变异,那么父组件就很难知道是什么导致了数据的变异