Vue不能观察到数组length的变化


Posted in Javascript onJune 08, 2018

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

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

为什么Vue不能观察到数组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 method
 const original = arrayProto[method]
 def(arrayMethods, method, function mutator (...args) {
  const result = original.apply(this, args)
  const ob = this.__ob__
  let inserted
  switch (method) {
   case 'push':
   case 'unshift':
    inserted = args
    break
   case 'splice':
    inserted = args.slice(2)
    break
  }
  if (inserted) ob.observeArray(inserted)
  // notify change
  ob.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的变化,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript 的继承
Oct 01 Javascript
JavaScript 学习笔记之操作符(续)
Jan 14 Javascript
理解 JavaScript Scoping & Hoisting(二)
Nov 18 Javascript
Bootstrap学习笔记之css样式设计(1)
Jun 07 Javascript
原生js实现淘宝购物车功能
Jun 23 Javascript
JavaScript html5利用FileReader实现上传功能
Mar 27 Javascript
jquery.rotate.js实现可选抽奖次数和中奖内容的转盘抽奖代码
Aug 23 jQuery
jQuery 实现左右两侧菜单添加、移除功能
Jan 02 jQuery
layui实现点击按钮给table添加一行
Aug 10 Javascript
require.js 加载过程与使用方法介绍
Oct 30 Javascript
js实现多图和单图上传显示
Dec 18 Javascript
Node登录权限验证token验证实现的方法示例
May 25 Javascript
Node.js中的child_process模块详解
Jun 08 #Javascript
详解使用 Node.js 开发简单的脚手架工具
Jun 08 #Javascript
使用JavaScript生成罗马字符的实例代码
Jun 08 #Javascript
jQuery实现表单动态加减、ajax表单提交功能
Jun 08 #jQuery
Node.js中你不可不精的Stream(流)
Jun 08 #Javascript
用react-redux实现react组件之间数据共享的方法
Jun 08 #Javascript
vue指令只能输入正数并且只能输入一个小数点的方法
Jun 08 #Javascript
You might like
老机欣赏|中国60年代精品收音机
2021/03/02 无线电
php引用地址改变变量值的问题
2012/03/23 PHP
php对数组排序代码分享
2014/02/24 PHP
php导入大量数据到mysql性能优化技巧
2014/12/29 PHP
php源码分析之DZX1.5字符串截断函数cutstr用法
2015/06/17 PHP
PHP基于openssl实现非对称加密代码实例
2020/06/19 PHP
用js实现预览待上传的本地图片
2007/03/15 Javascript
jquery validation插件表单验证的一个例子
2010/03/03 Javascript
javascript如何动态加载表格与动态添加表格行
2013/11/27 Javascript
JS+CSS实现带小三角指引的滑动门效果
2015/09/22 Javascript
javascript设计模式Constructor(构造器)模式
2016/08/19 Javascript
JavaScript正则表达式的贪婪匹配和非贪婪匹配
2017/09/05 Javascript
js实现单张图片平移切换效果
2017/10/11 Javascript
微信小程序解析富文本过程详解
2019/07/13 Javascript
JavaScript setInterval()与setTimeout()计时器
2019/12/27 Javascript
[52:44]VGJ.T vs infamous Supermajor小组赛D组败者组第一轮 BO3 第一场 6.3
2018/06/04 DOTA
对Python 网络设备巡检脚本的实例讲解
2018/04/22 Python
python更改已存在excel文件的方法
2018/05/03 Python
selenium+Chrome滑动验证码破解二(某某网站)
2019/12/17 Python
Python装饰器的应用场景代码总结
2020/04/10 Python
Keras之自定义损失(loss)函数用法说明
2020/06/10 Python
使用python-cv2实现Harr+Adaboost人脸识别的示例
2020/10/27 Python
python Timer 类使用介绍
2020/12/28 Python
HTML5页面嵌入小程序没有返回按钮及返回页面空白的问题
2020/05/28 HTML / CSS
AmazeUI导航的示例代码
2020/08/14 HTML / CSS
英国最大的电脑零售连锁店集团:PC World
2016/10/10 全球购物
世界上第一个水枕头:Mediflow
2018/12/06 全球购物
斐乐美国官方网站:FILA美国
2019/03/01 全球购物
洛杉矶时尚女装系列:J.ING US
2019/03/17 全球购物
自我鉴定怎么写
2013/12/05 职场文书
煤矿班组长岗位职责
2013/12/29 职场文书
幼儿园消防演练方案
2014/02/13 职场文书
个人债务授权委托书范本
2014/10/05 职场文书
redis不能访问本机真实ip地址的解决方案
2021/07/07 Redis
详解使用内网穿透工具Ngrok代理本地服务
2022/03/31 Servers
用Python仅20行代码编写一个简单的端口扫描器
2022/04/08 Python