Vue表单项赋值后无法输入问题解决

问题背景

  • 打开编辑页Form表单时,从后台接口获取已有数据并赋值到对应的输入框中,并通过v-model对数据进行绑定,会导致输入框输入无效的状态,且无报错信息
    问题分析
  1. Vue可以检测data中属性property的变化,但是不能直接检测数组、对象的变化
  2. 直接存在于data中的property可以检测并响应,但是后续定义并赋值property的无法检测
js 复制代码
// data
return {
  form: {}
}
// methods
getForm(res) {
  this.form = res.data
}

解决方法

  1. 通过forceUpdate强制更新,但是需要每个输入框都加(不推荐
  2. 赋值时通过扩展运算符...将源对象拷贝到目标对象(或者Object.assign等),表单中的控件会保持响应式,可以进行修改(推荐
js 复制代码
this.form = {...res.data}

原理拓展

  1. 为什么不能直接使用=给对象赋值
    • 在 Vue 中使用 v-model 将输入框与 form 对象的属性绑定时,Vue 会在内部为这些属性创建 getter 和 setter。这些 getter 和 setter 负责监听属性的变化并通知 Vue 响应式系统。这样,当输入框的值改变时,Vue 将自动更新相关的视图。
    • 然而,如果直接给 form 对象赋一个新的对象,Vue 就无法检测到对象的属性变化,因为此时 Vue 只是将新对象赋给了原来的引用,而不是修改了对象的属性。这就导致了输入框无法输入的问题,因为 Vue 没有监听到 form 对象的变化。
    • 使用 Object.assign() 或扩展运算符 ... 可以解决这个问题的原因在于它们都是在修改原对象的基础上进行的。虽然它们看起来像是将一个新的对象赋给了 form,但实际上是在原对象的基础上修改了属性。这样做会触发 Vue 的响应式系统,因为 Vue 会检测到属性的变化并更新视图。
  2. 可以使用深拷贝吗,有必要吗?
    • 可以使用深拷贝解决问题
    • 但是深拷贝并不是必要的,因为只需要确保更新对象的属性而不是整个对象。深拷贝会创建一个新的对象,这可能会导致性能开销较大,并且在大型对象上可能会引起不必要的复杂性。
    • 使用深拷贝虽然可以解决问题,但并不是最佳选择。相反,使用浅拷贝方法如 Object.assign() 或扩展运算符能够更有效地实现我们的目标,而且更符合这种情况的需求。
  3. JS直接赋值和浅拷贝的区别
    • 赋值,将一个对象赋值给一个新的对象的时候,赋的其实是该对象在栈中的地址,而不是堆中的数据。也就是一个对象的改变就会改变另外一个对象。
    • 浅拷贝,浅拷贝会创建一个对象,再去遍历原始对象,如果原对象的属性值是基础类型,那么就拷贝基础类型,如果是引用类型,则拷贝的是指针。
相关推荐
亭台烟雨中11 分钟前
【前端记事】关于electron的入门使用
前端·javascript·electron
泯泷25 分钟前
「译」解析 JavaScript 中的循环依赖
前端·javascript·架构
抹茶san27 分钟前
前端实战:从 0 开始搭建 pnpm 单一仓库(1)
前端·架构
Senar1 小时前
Web端选择本地文件的几种方式
前端·javascript·html
烛阴1 小时前
UV Coordinates & Uniforms -- OpenGL UV坐标和Uniform变量
前端·webgl
姑苏洛言1 小时前
扫码小程序实现仓库进销存管理中遇到的问题 setStorageSync 存储大小限制错误解决方案
前端·后端
烛阴1 小时前
JavaScript 的 8 大“阴间陷阱”,你绝对踩过!99% 程序员崩溃瞬间
前端·javascript·面试
lh_12542 小时前
ECharts 地图开发入门
前端·javascript·echarts