子组件修改数据影响父组件问题
当您在子组件中修改通过 props
传递的对象时,实际上您是在修改这个对象的引用,而这个引用同时也被父组件持有。在 JavaScript 中,对象是通过引用传递的,这意味着当您传递一个对象给一个函数或组件时,您实际上传递的是这个对象的引用。所以,当您在子组件中修改这个对象时,父组件中的相应对象也会发生变化,因为它们指向的是同一个内存地址。
为了避免这种情况,您可以在子组件中创建传递对象的深拷贝。这样,当您修改子组件中的对象时,不会影响父组件中的对象。深拷贝意味着创建一个新对象,并递归复制原始对象的所有属性到新对象中。
在 showModal
方法中,您可以使用深拷贝来创建 analysisForm
的副本,例如使用 JSON 的 parse
和 stringify
方法:
showModal(item, parsingFilesList) {
this.visible = true;
// 创建 item 的深拷贝
const analysisInit = JSON.parse(JSON.stringify(item));
// ...省略的代码...
// 现在 this.analysisForm 是一个深拷贝
this.analysisForm = analysisInit;
this.parsingFilesList = parsingFilesList;
// ...省略的代码...
}
请注意,使用 JSON 的 parse
和 stringify
方法进行深拷贝有一些局限性,比如它不能复制函数和 Symbol 类型的值。如果对象结构更复杂或包含特殊类型(例如函数、日期、RegExp 等),您可能需要一个更强大的深拷贝实现,例如使用 Lodash 库的 _.cloneDeep
方法。
如果 analysisForm
中的数据结构并不复杂,使用 JSON 方法进行深拷贝通常是足够的。但如果有特殊情况,您应该选择更适合的深拷贝方法。
我没通过props传递,我是通过this.$refs.CalculationDesignAnalysisModal.showModal(record, this.calculateForm.calculateInfo);这种 $refs 传递的
即使您没有通过 props
直接传递数据,但通过 $refs
调用子组件的方法并传递对象时,也是通过引用传递的。这意味着子组件和父组件中的 record
对象是同一个对象。因此,当您在子组件中修改这个对象时,实际上也修改了父组件中的对象。
为了防止这种情况,您应当在子组件中对传入的对象进行深拷贝,这样您就可以在子组件中操作这个对象的副本,而不会影响到父组件中的原始数据。以下是修改后的 showModal
方法,其中使用了 JSON.parse(JSON.stringify())
来创建 record
的深拷贝:
showModal(item, parsingFilesList) {
this.visible = true;
// 使用 JSON.parse(JSON.stringify(item)) 创建 item 的深拷贝
const analysisInit = JSON.parse(JSON.stringify(item));
// 其余的初始化代码
// ...
// 使用深拷贝的数据初始化 analysisForm
this.analysisForm = analysisInit;
this.parsingFilesList = parsingFilesList;
// 其余的初始化代码
// ...
}
现在,即使您在子组件中更改了 analysisForm
,它也不会影响到父组件中的 record
对象。
请注意,使用 JSON.parse(JSON.stringify())
进行深拷贝有局限性,它不能复制函数、undefined
、循环引用等。如果您的对象中包含这些类型的数据,您可能需要使用更复杂的深拷贝方法,例如使用 lodash 的 cloneDeep
函数。
在 Vue 中,通常建议避免直接修改父组件的状态,而是应该使用事件(通过 $emit
)将需要的更改发送回父组件,并让父组件负责更新状态。这样可以保持组件间的数据流向清晰,并有助于维护和调试。