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 文件的同步加载与异步加载实现原理
Dec 13 Javascript
js nextSibling属性和previousSibling属性概述及使用注意
Feb 16 Javascript
JavaScript中的apply和call函数详解
Jul 20 Javascript
js获取元素外链样式的方法
Jan 27 Javascript
javascript验证邮件地址和MX记录的方法
Jun 16 Javascript
vue引入swiper插件的使用实例
Jul 19 Javascript
vue组件实现文字居中对齐的方法
Aug 23 Javascript
vue里input根据value改变背景色的实例
Sep 29 Javascript
详解Vue2 添加对scss的支持
Jan 02 Javascript
说说Vuex的getters属性的具体用法
Apr 15 Javascript
jsonp跨域获取百度联想词的方法分析
May 13 Javascript
解决node.js含有%百分号时发送get请求时浏览器地址自动编码的问题
Nov 20 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模拟asp中的XmlHttpRequest实现http请求的代码
2011/03/24 PHP
php设计模式 DAO(数据访问对象模式)
2011/06/26 PHP
关于js与php互相传值的介绍
2013/06/25 PHP
WordPress中调试缩略图的相关PHP函数使用解析
2016/01/07 PHP
php下载文件,添加响应头的简单实例
2016/09/22 PHP
Laravel框架源码解析之模型Model原理与用法解析
2020/05/14 PHP
通过修改referer下载文件的方法
2008/05/11 Javascript
url 特殊字符 传递参数解决方法
2010/01/01 Javascript
JavaScript使用DeviceOne开发实战(一) 配置和起步
2015/12/01 Javascript
设置点击文本框或图片弹出日历控件的实现代码
2016/05/12 Javascript
Angualrjs和bootstrap相结合实现数据表格table
2017/03/30 Javascript
jquery实现图片放大点击切换
2017/06/06 jQuery
不到200行 JavaScript 代码实现富文本编辑器的方法
2018/01/03 Javascript
JS正则表达式封装与使用操作示例
2019/05/15 Javascript
[00:27]DOTA2战队VP、Secret贺新春
2018/02/11 DOTA
[01:20]2018DOTA2亚洲邀请赛总决赛战队LGD晋级之路
2018/04/07 DOTA
[56:48]FNATIC vs EG 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python Mysql自动备份脚本
2008/07/14 Python
python网络爬虫采集联想词示例
2014/02/11 Python
深度剖析使用python抓取网页正文的源码
2014/06/11 Python
Windows安装Python、pip、easy_install的方法
2017/03/05 Python
Python实现网站注册验证码生成类
2017/06/08 Python
Python3使用PyQt5制作简单的画板/手写板实例
2017/10/19 Python
使用pandas批量处理矢量化字符串的实例讲解
2018/07/10 Python
python实现自动化上线脚本的示例
2019/07/01 Python
Python3 翻转二叉树的实现
2019/09/30 Python
python利用pytesseract 实现本地识别图片文字
2020/12/14 Python
泰国健康和美容服务预订网站:GoWabi
2019/06/03 全球购物
荷兰天然和有机产品网上商城:BigGreenSmile.nl
2020/07/26 全球购物
Android面试题及答案
2015/09/04 面试题
药品质量检测应届生求职信
2013/11/14 职场文书
日语求职信范文
2013/12/17 职场文书
十八大演讲稿
2014/05/22 职场文书
自愿解除劳动合同协议书
2014/09/11 职场文书
如何解决springcloud feign 首次调用100%失败的问题
2021/06/23 Java/Android
python中urllib包的网络请求教程
2022/04/19 Python