vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue 数据丢失

Vue 中数据丢失响应式的原因和解决方案

作者:MXN_小南学前端

本文给大家介绍Vue中数据丢失响应式的原因和解决方案,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

在 Vue 开发里,很多人都遇到过这种情况:

其实,这类问题大多不是 Vue “坏了”,而是你操作数据的方式绕开了响应式系统。这篇文章就来系统讲一下:Vue 中数据为什么会丢失响应式,以及怎么解决。

一、什么是响应式

Vue 的核心能力之一,就是把数据和视图绑定起来:

也就是说,Vue 会在你修改数据时,自动侦测变化并触发重新渲染。

但这个能力有前提:数据必须处于 Vue 的响应式系统里

二、数据丢失响应式的常见原因

1. 直接给对象新增属性

这是 Vue 2 里最经典的问题。

data() {
  return {
    form: {}
  }
}

后面你这样写:

this.form.name = '张三'

在 Vue 2 中,name 这个字段一开始不存在,所以 Vue 没有为它建立响应式监听,页面可能不会更新。

为什么会这样

Vue 2 使用的是 Object.defineProperty,它只能在初始化时把已有属性转成响应式。
后面新增的字段,它不知道。

2. 直接修改数组索引

this.list[0] = 'new value'

或者:

this.list.length = 0

在 Vue 2 中,这些写法也可能无法触发更新。

原因

Vue 2 无法拦截数组索引赋值和长度修改,因此不一定能检测到变化。

3. 解构响应式对象,导致响应式丢失

比如在 Vue 3 里:

const state = reactive({
  name: 'Tom',
  age: 18
})
const { name } = state

这里的 name 已经不再是响应式引用了,只是一个普通变量。

为什么

解构后拿到的是值,不再通过原来的代理对象访问,所以丢失了跟踪能力。

4. 使用了普通对象副本

const newForm = { ...this.form }

这个 newForm 只是一个普通对象,不是 Vue 的响应式代理对象。

如果你后面一直操作这个副本,页面当然不会跟着变。

5.ref/reactive用法不当

在 Vue 3 中:

const count = ref(0)

需要通过:

count.value++

如果你写成:

const value = count.value
value++

那么 value 只是一个普通变量,和响应式源已经脱钩了。

6. 对响应式对象做了深拷贝

const copy = JSON.parse(JSON.stringify(state))

这样会得到一个全新的普通对象,响应式自然就没了。

7. 使用了markRaw、shallowReactive、shallowRef

这些 API 本身就会让响应式“变浅”或者直接跳过代理。

例如:

const obj = markRaw({
  name: 'Tom'
})

这个对象不会被 Vue 深度代理。

三、Vue 2 和 Vue 3 的区别

Vue 2

Vue 2 基于 Object.defineProperty,所以有这些典型限制:

Vue 3

Vue 3 基于 Proxy,能力强很多:

所以 Vue 3 比 Vue 2 省心很多,但它也不是“完全不会丢响应式”,只是丢失的场景变少了,主要集中在:

四、怎么解决

1. Vue 2 中新增属性用Vue.set或this.$set

this.$set(this.form, 'name', '张三')

这样 Vue 会把新字段补成响应式。

2. Vue 2 中修改数组用splice

this.list.splice(0, 1, 'new value')

而不是:

this.list[0] = 'new value'

3. 初始化时把字段都声明好

这是最稳的方式。

data() {
  return {
    form: {
      name: '',
      age: '',
      address: ''
    }
  }
}

这样后面你直接:

this.form.name = '张三'

就不会有问题。

4. Vue 3 中避免直接解构响应式对象

错误写法:

const state = reactive({
  form: { name: 'Tom' }
})
const { form } = state

推荐写法:

const state = reactive({
  form: { name: 'Tom' }
})
const form = toRef(state, 'form')

或者:

const { form } = toRefs(state)

5. 不要随手把响应式对象转成普通副本

如果你只是为了临时显示,可以复制。
如果你还想继续响应式更新,就不要拷贝成普通对象。

6. 注意ref的.value

Vue 3 里:

const count = ref(0)
count.value++

这是正确的。

五、怎么判断是不是“丢失响应式”

你可以用这几个方法排查:

如果数据变了但页面没变,大概率就是:

  1. 没有被 Vue 追踪
  2. 操作方式绕开了响应式
  3. 视图依赖的不是你改的那个对象

六、总结

Vue 数据丢失响应式,本质上就一句话:

你改的不是 Vue 追踪的那个数据源,或者你修改的方式没有被 Vue 捕获。

Vue 2 重点记住:

Vue 3 重点记住:

到此这篇关于Vue 中数据丢失响应式的原因和解决方案的文章就介绍到这了,更多相关Vue 数据丢失内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文