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 相关文章推荐
dojo 之基础篇(三)之向服务器发送数据
Mar 24 Javascript
jsonp原理及使用
Oct 28 Javascript
jquery实现一个简单好用的弹出框
Sep 26 Javascript
node.js中使用socket.io的方法
Dec 15 Javascript
简单了解JavaScript操作XPath的一些基本方法
Jun 03 Javascript
JavaScript正则获取地址栏中参数的方法
Mar 02 Javascript
原生JS改变透明度实现轮播效果
Mar 24 Javascript
vue.js实现插入数值与表达式的方法分析
Jul 06 Javascript
vue-cli 3.x 修改dist路径的方法
Sep 19 Javascript
彻底弄懂 JavaScript 执行机制
Oct 23 Javascript
深入浅析javascript函数中with
Oct 28 Javascript
Element-UI+Vue模式使用总结
Jan 02 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
PHP5与MySQL数据库操作常用代码 收集
2010/03/21 PHP
PHP利用header跳转失效的解决方法
2014/10/24 PHP
php正则替换处理HTML页面的方法
2015/06/17 PHP
Laravel5权限管理方法详解
2016/07/26 PHP
jquery插件如何使用 jQuery操作Cookie插件使用介绍
2012/12/15 Javascript
javascript验证身份证完全方法具体实现
2013/11/18 Javascript
JavaScript修改css样式style动态改变元素样式
2013/12/16 Javascript
用JavaScript实现使用鼠标画线的示例代码
2014/08/19 Javascript
创建、调用JavaScript对象的方法集锦
2014/12/24 Javascript
Javascript仿新浪游戏频道鼠标悬停显示子菜单效果
2015/08/21 Javascript
jquery操作ID带有变量的节点实例
2016/12/07 Javascript
jquery中$.fn和图片滚动效果实现的必备知识总结
2017/04/21 jQuery
基于input框覆盖掉数字英文的实例讲解
2017/07/21 Javascript
Bootstrap table中toolbar新增条件查询及refresh参数使用方法
2018/05/18 Javascript
django中使用vue.js的要点总结
2019/07/07 Javascript
vue iview多张图片大图预览、缩放翻转
2019/07/13 Javascript
ES6 async、await的基本使用方法示例
2020/06/06 Javascript
Vue检测屏幕变化来改变不同的charts样式实例
2020/10/26 Javascript
python操作MySQL数据库具体方法
2013/10/28 Python
python常见数制转换实例分析
2015/05/09 Python
Python使用CMD模块更优雅的运行脚本
2015/05/11 Python
python编写爬虫小程序
2015/05/14 Python
Python yield 使用方法浅析
2017/05/20 Python
python Matplotlib画图之调整字体大小的示例
2017/11/20 Python
python实现kNN算法
2017/12/20 Python
Python元组及文件核心对象类型详解
2018/02/11 Python
python3获取两个日期之间所有日期,以及比较大小的实例
2018/04/08 Python
详解用pyecharts Geo实现动态数据热力图城市找不到问题解决
2019/06/26 Python
python程序运行进程、使用时间、剩余时间显示功能的实现代码
2019/07/11 Python
详解python内置常用高阶函数(列出了5个常用的)
2020/02/21 Python
浅谈Python中的生成器和迭代器
2020/06/19 Python
Skip Hop官网:好莱坞宝宝挚爱品牌
2018/06/17 全球购物
澳大利亚最大的百货公司:Myer
2018/12/21 全球购物
个人课题方案
2014/05/08 职场文书
MBA推荐信怎么写
2015/03/25 职场文书
谢师宴家长致辞
2015/07/27 职场文书