Vue2 校验不通过的表单,赋正确的值后,再次校验结果不变
前言
在工作中遇到了这个问题,多次排查,耗费了不少时间才解决这个问题。问题的解决很简单,但发现根本原因还是有点困难,因此在此做个记录,以防忘记。
问题发现步骤
例如有以下 Ant Design Vue 表单
<a-form-model ref="formRef" :model="model">
<a-form-model-item label="姓名" prop="name" :rules="[{ required: true, message: '请填写姓名', trigger: 'blur' }]">
<a-input v-model="model.name" placeholder="请输入姓名"></a-input>
</a-form-model-item>
<a-form-model-item label="留言" prop="notes" :rules="[{ required: true, message: '请填写留言', trigger: 'blur' }]">
<a-input v-model="model.notes" placeholder="请输入留言"></a-input>
</a-form-model-item>
<a-form-model/>
然后进行以下步骤
1.留言项输入内容,然后通过
this.$refs.refForm.validate()
进行表单校验,这时候会报姓名项为必填项的错误;
2.然后通过事件为model.name
赋值,例如this.model = Object.assign(this.model, { name: '123' })
,赋值后重新进行表单校验,此时依旧报姓名项为必填项的错误;
其他现象
3.打印
this.model
,得到的是正确的值console.log(this.model) // { name: '123', notes: '之前输入的内容' }
4.直接在 input 输入框上填写内容,把内容从 ‘123’,改为 ‘test’,填写完后,刚填写的 ‘test’ 又变回了 ‘123’,打印
this.model
,得到的是新的值console.log(this.model) // { name: 'test', notes: '之前输入的内容' }
后续判断为 this.model
对象失去了响应性。
解决
去搜相关内容,搜到的大都说 Object.assign()
会保留对象的响应性,直接赋值才会丢失响应性
this.model = Object.assign(this.model, { name: '123' }) // 保留响应性 ?
this.model = { name: '123', notes: '之前输入的内容' } // 丢失响应性 ?
但根据实际情况和这个问题的表现,证明 this.model = Object.assign(this.model, { name: '123' })
这样也会丢失响应性。
最终的解决方法在官方文档 深入响应式原理 这部分
有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })` this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
所以实际是:
this.model = Object.assign(this.model, { name: '123' }) // 丢失响应性
this.model = Object.assign({}, this.model, { name: '123' }) // 保留响应性