在实际开发中,遇到遍历数组和对象,当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. 为datagridview添加自定义按钮

    先上图: 我是直接网上搜得代码,不是本人写得.下面说说大体思路,继承DataGridViewButtonCell类实现自定义类比如这个:DataGridViewDetailButtonCell 里面, ...

  2. HTML——input之密码框

    在 HTML 中,把 <input> 标签的 type 属性设置为 password 可以表示密码框.具体语法格式如下: <input type="password&quo ...

  3. AIAGC导航(aiagc.com): 最全的AI工具导航网站

    AIAGC导航是一个专注于AI人工智能工具网站推荐的导航网站,可以帮助大家发现最新.最好用.最有趣的AI绘画.AI智能写作助手.AI聊天机器人.AI配音.AI音乐.AI换脸等各种AI工具应用软件,让A ...

  4. 腾讯消息队列CMQ一键化部署脚本

    CMQ-1.0.2-软件包.tar安装包放在家目录,脚本也放在家目录,然后执行:sh -x cmq_install.sh [ip1] [ip2] [ip3] 即可 下列脚本代码保存为:cmq_inst ...

  5. 8.18考试总结(NOIP模拟43)[第一题·第二题·第三题·第四题]

    愿你和重要的人,在来日重逢. 前言 题目名字起的很随意... 这天 Luogu 的运势好像是大凶(忌:打模拟赛,注意报零). 但是考得还不错,拿到了这么多场模拟赛以来第二三个场上AC. 所以说,我爱大 ...

  6. .net core .net6 webapi 连接mysql 8

    1.表结构: CREATE TABLE `table2` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `myname` varchar(255) NOT NULL, ...

  7. C#.NET HTTP Request 跳过自签名证书校验。

    public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain ...

  8. 如何排查常规软件问题 - 面向 Linux 初级用户的教程

    笔者从 14 年做开源软件以来,接触了众多 Linux 新手用户,这里我为这类用户总结了一些常见的问题排查方法,希望能帮助到大家.如果你已经工作多年,对于下面提到的思路和方法应该非常熟悉,如果对某一条 ...

  9. Vue学习:12.生命周期实例

    两个小例子,巩固一下生命周期钩子函数. 实例1:初始化渲染 实现功能: 在 Vue 实例数据为空的情况下,用户在一进入页面就向服务器发送请求获取数据,并在数据返回后进行动态渲染. 思路: 创建一个 V ...

  10. 获取前(后)x月的日期

    package com.jesims.busresume.web; import org.springframework.stereotype.Service; import java.text.Da ...