封装的 el-dialog 组件 emit 传递数据后初始化,父组件的数据为什么也被初始化了?

以下是封装的el-dialog组件中方法,执行emit方法后调用了closeHandler初始化,为什么父组件的dataForm数据也被初始化了?

/**
 * 将表单信息传给父组件
 */
async emit() {
  const valid = await this.$refs.dataForm.validate().catch(() => {});
  if (!valid) return this.$message.warning('请先完善信息!');

  this.$emit('dataForm', this.dataForm);

  this.close();
},
/**
 * 关闭
 */
close() {
  this.dialogVisible = false;
},
/**
 * 绑定到 el-dialog 的 @closed 事件
 * 关闭弹窗后,重置数据
 */
closedHandler() {
  this.$refs.dataForm.resetFields();
},

假设dataForm初始化为:

data: () => ({
  dataForm: { name: '', age: 0 }
})

在表单输入数据后应为:

data: () => ({
  dataForm: { name: '张三', age: 18 }
})

而实际父组件使用的则是:

data: () => ({
  dataForm: { name: '', age: 0 }
})
阅读 1.7k
2 个回答

在你回传的这一步

 this.$emit('dataForm', this.dataForm);

表单数据确实已经被回传给父组件了,但紧接着你调用了this.close();关闭弹窗,导致表单数据被closedHandler函数清空了

所以你的标题应该是emit传递表单数据后表单数据被清空,而非传递的是初始值


至于为什么你觉得父组件收到的是重置后的数据,可能有下面两种情况
1.父组件异步使用数据
父组件在接收 dataForm事件后,没有立即使用数据,等实际用到数据时,弹窗已关闭,表单已被重置。

2.父组件直接引用了对象
如果父组件直接保存了 this.dataForm的引用,而非复制数据,当子组件重置表单时,父组件引用的对象内容也被同步修改了(因为JS对象是引用传递)。

解决方式也很简单,你可以验证一下:
1.父组件立即深拷贝数据
在父组件接收事件时,立刻复制一份数据,避免后续被修改:

// 父组件
handleDataForm(formData) {
  // 深拷贝保存数据(用 JSON 或 lodash.cloneDeep)
  this.formData = JSON.parse(JSON.stringify(formData)); 
}

2.子组件延迟重置
closedHandler中加延时,确保父组件先处理完数据:

closedHandler() {
  setTimeout(() => {
    this.$refs.dataForm.resetFields(); // 等父组件处理完再重置
  }, 1000);
}

可能是对象引用
this.$emit('dataForm', { ...this.dataForm });

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题