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(AJAX)解析XML的代码(兼容FIREFOX/IE)
Jul 11 Javascript
js网页侧边随页面滚动广告效果实现
Apr 14 Javascript
使用jQuery fancybox插件打造一个实用的数据传输模态弹出窗体
Jan 15 Javascript
JavaScript转换二进制编码为ASCII码的方法
Apr 16 Javascript
js改变Iframe中Src的方法
May 05 Javascript
把Node.js程序加入服务实现随机启动
Jun 25 Javascript
javascript省市区三级联动下拉框菜单实例演示
Nov 29 Javascript
js+canvas绘制矩形的方法
Jan 28 Javascript
jQuery 全选 全部选 反选 实现代码
Aug 17 Javascript
js对象实例详解(JavaScript对象深度剖析,深度理解js对象)
Sep 21 Javascript
vue 获取元素额外生成的data-v-xxx操作
Sep 09 Javascript
微信小程序调用后台service教程详解
Nov 06 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
php循环检测目录是否存在并创建(循环创建目录)
2011/01/06 PHP
在Yii2中使用Pjax导致Yii2内联脚本载入失败的原因分析
2016/03/06 PHP
删除PHP数组中头部、尾部、任意元素的实现代码
2017/04/10 PHP
详解laravel安装使用Passport(Api认证)
2018/07/27 PHP
JavaScript 参考教程
2006/12/29 Javascript
js一般方法改写成面向对象方法的无限级折叠菜单示例代码
2013/07/04 Javascript
js日期联动示例
2014/05/02 Javascript
一个不错的字符串转码解码函数(自写)
2014/07/31 Javascript
js鼠标点击图片切换效果实现代码
2015/11/19 Javascript
详解Bootstrap的aria-label和aria-labelledby应用
2016/01/04 Javascript
jQuery的图片轮播插件PgwSlideshow使用详解
2016/08/11 Javascript
jQuery 获取select选中值及清除选中状态
2016/12/13 Javascript
javascript 单例模式详解及简单实例
2017/02/14 Javascript
Vue2.0学习之详解Vue 组件及父子组件通信
2017/12/12 Javascript
微信小程序之裁剪图片成圆形的实现代码
2018/10/11 Javascript
关于AOP在JS中的实现与应用详解
2019/05/06 Javascript
layui table数据修改的回显方法
2019/09/04 Javascript
2019最新21个MySQL高频面试题介绍
2020/02/06 Javascript
vue通过过滤器实现数据格式化
2020/07/20 Javascript
js实现滑动滑块验证登录
2020/07/24 Javascript
H5+css3+js搭建带验证码的登录页面
2020/10/11 Javascript
微信小程序实现单个或多个倒计时功能
2020/11/01 Javascript
一个简单的python程序实例(通讯录)
2013/11/29 Python
python对数组进行反转的方法
2015/05/20 Python
Django中ORM外键和表的关系详解
2019/05/20 Python
python射线法判断一个点在图形区域内外
2019/06/28 Python
matplotlib 画双轴子图无法显示x轴的解决方法
2020/07/27 Python
在django中查询获取数据,get, filter,all(),values()操作
2020/08/09 Python
提高EJB性能都有哪些技巧
2012/03/25 面试题
借款担保书范文
2014/05/13 职场文书
省级优秀毕业生主要事迹
2014/05/29 职场文书
拾金不昧表扬稿
2015/01/16 职场文书
个人工作保证书
2015/02/28 职场文书
2015年信访工作总结
2015/04/07 职场文书
老乡会致辞
2015/07/28 职场文书
使用 Koa + TS + ESLlint 搭建node服务器的过程详解
2022/05/30 NodeJs