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直接赋值和浅拷贝的区别
    • 赋值,将一个对象赋值给一个新的对象的时候,赋的其实是该对象在栈中的地址,而不是堆中的数据。也就是一个对象的改变就会改变另外一个对象。
    • 浅拷贝,浅拷贝会创建一个对象,再去遍历原始对象,如果原对象的属性值是基础类型,那么就拷贝基础类型,如果是引用类型,则拷贝的是指针。
相关推荐
腾讯TNTWeb前端团队4 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰7 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪7 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪8 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy8 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom9 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom9 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom9 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom9 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom9 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试