官网解释如下

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

因为vue的响应式是通过Object.defineProperty来实现的,但是数组的length属性是不能添加getter和setter,所有无法通过观察length来判断。

例子

如下代码,虽然看起来数组的length是10,但是for in的时候只能遍历出0, 1, 2,导致了只有前三个索引被加上了getter 和setter

var a = [0, 1, 2]
a.length = 10
// 只是显示的给length赋值,索引3-9的对应的value也会赋值undefined
// 但是索引3-9的key都是没有值的
// 我们可以用for-in打印,只会打印0,1,2
for (var key in a) {console.log(key) // 0,1,2
}

那么vue提供了一些解决方法

使用内置的Vue.$set

让数组显式的进行某个索引的观察 Vue.set(array, indexOfItem, newValue)

实际上是调用了

Object.defineProperty(array, indexOfItem, {enumerable: true,configurable: true,get() { },set(newVal) { }
})

这样可以手动指定需要观察的key,那么就可以达到预期的效果。

重写了 push, pop, shift, unshift, splice, sort, reverse方法

Vue源码

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)/*** Intercept mutating methods and emit events*/
;['push','pop','shift','unshift','splice','sort','reverse'
]
.forEach(function (method) {// cache original methodconst original = arrayProto[method]def(arrayMethods, method, function mutator (...args) {const result = original.apply(this, args)const ob = this.__ob__let insertedswitch (method) {case 'push':case 'unshift':inserted = argsbreakcase 'splice':inserted = args.slice(2)break}if (inserted) ob.observeArray(inserted)// notify changeob.dep.notify()return result})
})

这些是在Array.__proto__上 进行了方法重写或者添加

并且对添加属性的方法如push,unshift,splice所添加进来的新属性进行手动观察,源码为

  if (inserted) ob.observeArray(inserted)

对以上方法进行了手动的进行消息触发

  ob.dep.notify()

结论

vue对数组的length直接改变无法直接进行观察,提供了vue.$set 进行显式观察,并且重写了 push, pop, shift, unshift, splice, sort, reverse方法来进行隐式观察。

为什么Vue不能观察到数组length的变化?相关推荐

  1. [vue] 分别说说vue能监听到数组或对象变化的场景,还有哪些场景是监听不到的?无法监听时有什么解决方案?

    [vue] 分别说说vue能监听到数组或对象变化的场景,还有哪些场景是监听不到的?无法监听时有什么解决方案? 无法监听时的方案: 数组:改变数组的值:this.$set() 改变数组长度:arr.sp ...

  2. vue 监听map数组变化_解决vue无法侦听数组及对象属性的变化问题

    一.数组 1.可以监听到的情况 如push.splice.=赋值(array=[1,2,3]) 2.无法监听到的情况 使用下标修改某个元素(这种比较常见) array[index] = 1 objec ...

  3. arr数组怎么取值_记一次思否问答的问题思考:Vue为什么不能检测数组变动

    作者 | hfhan 来源 | https://segmentfault.com/a/1190000015783546 问题描述:Vue检测数据的变动是通过Object.defineProperty实 ...

  4. vue使用js遍历数组和对象

    前言 在vue中,遍历数组和对象的方式略有不同,不能完全以数组或对象的遍历方式给对方使用并获取数据.为了记录以及以后方便查看,现在对其进行整理. 数组遍历 以数组 array = [1,2,3,4,5 ...

  5. VUE 模板 v-if 判断 数组是否为空

    vue 模板 v-if 判断数组是否为空 : 为空:array == undefined ||array == null || array.length <= 0 (顺序不能调换)不为空: ar ...

  6. Vue观察对象的子属性变化,wacth的deep使用

    我们都已经知道,如何观察一个属性值的变化,然后做相应的操作.比如我有一个属性name,我希望在name改变的时候,弹出消息框. 代码如下: <template><div id=&qu ...

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

    vue数组中数据变化但是视图没有更新解决方案 参考文章: (1)vue数组中数据变化但是视图没有更新解决方案 (2)https://www.cnblogs.com/sufubo/p/6906261.h ...

  8. Vue中实现清空数组和清空el-table

    场景 要实现的效果是 那么就要用到怎样将这个el-table清空,即在vue中怎样将数组清空. 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公 ...

  9. [vue] vue能监听到数组变化的方法有哪些?为什么这些方法能监听到呢?

    [vue] vue能监听到数组变化的方法有哪些?为什么这些方法能监听到呢? 你说的是vue内部的源码对Array数据的中转代理嘛 好像对push, shift等通用方法都做了代理吧! 因为它对中转的数 ...

最新文章

  1. 26个音序的正确写法和占格_部编语文汉语拼音音序表,示范朗读+视频教学
  2. eclipse从数据库逆向生成Hibernate实体类
  3. 【FTP】FTP服务器的搭建
  4. dbgrid的最小高度设置。否则出现滚动条。
  5. Java只用一个循环语句输出九九乘法表
  6. 淘宝现在什么类目比较好做?
  7. web用css做网页实验报告,Web实验报告网页设计与制作
  8. [原创]解决Heritrix镜像方式存储路径中文乱码的解决方案
  9. Msm8960(APQ8064)平台的MSM-AOSP-kitkat编译适配(7):信号通讯
  10. python:实现convolve卷积算法(附完整源码)
  11. 博客线下推广的小技巧
  12. 阿里云国际版ECS云服务器ping不通的原因分析
  13. Ubuntu如何通过简单的几步操作来配置系统的软件源、找不到软件和更新怎么办?(带动态图文介绍)
  14. 网络云存储技术Windows server 2012 (项目十 基于NTFS权限(ADLP原则)的文件共享服务的配置与管理)
  15. JVM学习笔记(二):垃圾回收、垃圾回收算法、垃圾回收器(Serial、Parallel、CMC、G1)、内存分配原则实战
  16. 钱多多的程序猿的2020大计划
  17. 软件框架-无绪开发4
  18. 关联规则挖掘算法: Aprior算法和Fpgrowth算法
  19. 为什么我放弃了有道云笔记,选择了 Obsidian
  20. pointer和reference(指针和引用)的区别:*

热门文章

  1. win mysql 2003错误_windows MySql 报1067错误 2003错误
  2. .Net Core3 新特性整理
  3. 关于前端设置cookie
  4. MySQL--开发技巧(一)
  5. Java集合框架练习-计算表达式的值
  6. MySQL : 报错:1130-host ... is not allowed to connect to this MySql server 开放mysql远程连接 不使用localhost...
  7. 字符串字符和数字分割
  8. 1. ThreadPoolExecutor的一个常用的构造方法
  9. Mathematics 9.0 绘制不等式确定的区域
  10. 关于摄像头的一些零碎知识