在实际开发中,遇到遍历数组和对象,当property 发生改变时,并没有触发视图的更新今天来浅显的聊聊这背后的故事,有说的不对地方,还望指出!

本人博文地址:https://www.cnblogs.com/echoyya/p/14041271.html

Vue 如何追踪数据变化

参考文献:官网 vue.js

把一个普通的 JS 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。需注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

检测变化的注意事项

由于 JS 的限制,Vue 不能检测数组对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性。

对于对象

  1. Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。那么该如何能判定一个property是否是响应式呢,例如:

  2. 对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如:

var vm = new Vue({
data:{
user:{
name:'nhy'
}
}
})
Vue.set(vm.user, 'age', 24)

还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:

this.$set(this.user,'age',24)

  1. 有时可能需要为已有对象赋值多个新 property,比如使用 Object.assign()_.extend()。但是,这样添加到对象上的新 property 不会触发更新,此时应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。
// 代替 Object.assign(this.user, { a: 1, b: 2 })
this.user = Object.assign({}, this.user, { a: 1, b: 2 })

对于数组

Vue 不能检测以下数组的变动:

  1. 当你利用索引直接设置一个数组项时,vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,vm.items.length = newLength
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
}) vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

第一类问题:以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue) // Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:

vm.$set(vm.items, indexOfItem, newValue)

第二类问题,可以使用 splice:

vm.items.splice(newLength)

那么言归正传,还是要总结一下的

  1. 运用 this.$forceUpdate() 强制刷新。

  2. 对于对象

    • Vue.set(object, propertyName, value)

    • this.$set(this.someObject, propertyName, value)

    • this.someObject= Object.assign({}, this.someObject, { a: 1, b: 2 })

  3. 对于数组

    • Vue.set(vm.items, index, newValue)

    • vm.$set(vm.items, index, newValue)

    • vm.items.splice(index, 1, newValue)

    • vm.items.splice(newLength)

Vue 数组和对象更新,但视图未更新,背后的故事的更多相关文章

  1. vue 路由更新页面视图未更新问题

    最近项目做面包屑的时候遇到一个问题就是路由变化的时候页面视图并没有发生变化,后来上网查,发现是vue-router的特性导致的. vue-router的切换不同于传统的页面的切换.路由之间的切换,其实 ...

  2. vue数组中数据变化但是视图没有更新解决方案

    原文链接:http://www.cnblogs.com/sufubo/p/6906261.html#undefined 问题:在vue项目中,我更改数组中的某一条数据,直接arr[i]=newVal ...

  3. vue 数组和对象渲染问题

    vue 数组和对象渲染问题 最近项目有点忙碌,遇到好多问题都没有总结(╥﹏╥),在开发过程中,取vuex中的数组渲染完成之后,再次修改数组的值,数据更新了,但是视图并没有更新.以为是数组更新的问题,后 ...

  4. vue修改elementUI的分页组件视图没更新问题

    转: vue修改elementUI的分页组件视图没更新问题 今天遇到一个小问题平时没留意,el-pagination这个分页组件有一个属性是current-page当前页.今天想在methods里面手 ...

  5. 解决vue中对象属性改变视图不更新的问题

    在使用VUE的过程中,会遇到这样一种情况, vue data 中的数据更新后,视图没有自动更新. 这个情况一般分为两种, 一种是数组的值改变,在改变数组的值的是时候使用索引值去更改某一项,这样视图不会 ...

  6. vue数组中对象属性变化页面不渲染问题

    问题引入 Vue之所以能够监听Model状态的变化,是因为JavaScript语言本身提供了Proxy或者Object.observe()机制来监听对象状态的变化.但是,对于数组元素的赋值,却没有办法 ...

  7. vue中修改了数据但视图无法更新的情况[转载]

    我们有时候常碰到vue中明明修改了数据,但是视图无法更新,因此我总结了一点点碰到此类的情况: 1.v-for遍历的数组,当数组内容使用的是arr[0].xx =xx更改数据,vue无法监测到 数组数据 ...

  8. vue 数组和对象不能直接赋值情况和解决方法

    Vue 不能检测以下变动的数组: 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue 当你修改数组的长度时,例如:vm.items.length = ...

  9. vue 数组、对象 深度拷贝和赋值

    由于此对象的引用类型指向的都是一个地址(除了基本类型跟null,对象之间的赋值,只是将地址指向同一个,而不是真正意义上的拷贝) 数组: let a = [11,22,33]; let b = a; / ...

  10. vue---数据更新,视图不更新问题

    写点赞功能时,点赞后已经追加到对象里了,但是视图没有更新. 查找了些资料: 数据已经更新了但是视图不更新的问题,有几个原因: 1.根属性不存在,而想要直接给根属性赋值导致的视图不更新.此时初始化属性的 ...

随机推荐

  1. 为什么不推荐在Spring Boot中使用@Value加载配置

    @Value注解相信很多Spring Boot的开发者都已经有接触了,通过使用该注解,我们可以快速的把配置信息加载到Spring的Bean中. 比如下面这样,就可以轻松的把配置文件中key为com.d ...

  2. MyBatis一对多或多对多分页查询的结果条数不符合预期的问题解决

    问题描述 ​ 通常我们我们在单表查询中我们可以采用limit进行分页查询,这样可以减少页面的显示量,加快页面想应速度.但是在MyBatis框架中,如果我们在一对多或多对多查询中直接使用limit关键字 ...

  3. linux系统下,安装maven教程

    1.下载 官网:https://maven.apache.org/download.cgi 2.上传包 将下载好的maven安装包apache-maven-3.8.6-bin.tar.gz放在磁盘的 ...

  4. 为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?

    Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的.而 Mybatis 在查询关联对象或关联集合 ...

  5. 3个线程分别交替输出xyz字符,输出10遍

    一位群友分享的**公司面试题 3个线程分别交替输出xyz字符,输出10遍 public class XYZ implements Runnable { private static AtomicInt ...

  6. php des加密用java解析不了 改个模式 加个IV php密钥/IV要求都是8位

    php des加密用java解析不了 改个模式 加个IV  php密钥/IV要求都是8位 php des加密用java解析不了 Wrong IV length: must be 8 bytes lon ...

  7. 笔记:Sublime Text3配置

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 笔记:Sublime Text3配置 日期:2017-12 ...

  8. uniapp iphone 6s获取时间戳失败

    上代码 时间格式:2023-10-11 00:00:00 var ms = new Date(item.content.goodsList[0].end_time).getTime() 使用iphon ...

  9. Pytest 失败重运行

    需安装第三方插件:pytest-rerun.pytest-rerunfailures 失败重试和失败重运行的区别 失败重试:[--reruns=1],用例执行失败后,会立即开始重试一次此用例,再执行下 ...

  10. C++面向对象多级菜单向Arduino的移植

    前段时间写了一篇文章<C++面向对象语言自制多级菜单>,文中指出了可以将HeleMenu库进行移植,现已完成技术思路,特此记录. 一.特性 基本与上一篇文章指出的一致,只是将菜单显示和响应 ...