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

 更新时间:2018年06月08日 13:42:23   作者:buyue  
因为vue的响应式是通过 Object.defineProperty 来实现的,但是数组的length属性是不能添加getter和setter,所有无法通过观察length来判断。这篇文章主要介绍了为什么Vue不能观察到数组length的变化,需要的朋友可以参考下

由于 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的变化,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • 深入浅析Vue.js中 computed和methods不同机制

    深入浅析Vue.js中 computed和methods不同机制

    这篇文章给大家介绍了Vue.js中 computed和methods不同机制,在vue.js中,methods和computed两种方式来动态当作方法使用,文中还给大家提到了computed和methods的区别,感兴趣的朋友一起看看吧
    2018-03-03
  • vue 项目@change多个参数传值多个事件的操作

    vue 项目@change多个参数传值多个事件的操作

    这篇文章主要介绍了vue 项目@change多个参数传值多个事件的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • Vue.js创建Calendar日历效果

    Vue.js创建Calendar日历效果

    这篇文章主要为大家详细介绍了Vue.js创建Calendar日历效果的过程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • vue3解决各场景loading过度的五种方法

    vue3解决各场景loading过度的五种方法

    这篇文章主要为大家详细介绍了vue3中解决各场景loading过度的五种方法,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以学习一下
    2023-11-11
  • vue中选中多个选项并且改变选中的样式的实例代码

    vue中选中多个选项并且改变选中的样式的实例代码

    这篇文章主要介绍了vue中选中多个选项并且改变选中的样式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • 详解vue 自定义marquee无缝滚动组件

    详解vue 自定义marquee无缝滚动组件

    这篇文章主要介绍了vue自定义marquee无缝滚动组件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • 一步步讲解Vue如何启动项目

    一步步讲解Vue如何启动项目

    这篇文章主要给大家介绍了关于Vue如何启动项目的相关资料,还介绍了解决vue启动项目时间很长问题的相关方法,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Vue 3自定义指令开发的相关总结

    Vue 3自定义指令开发的相关总结

    这篇文章主要介绍了Vue 3自定义指令开发的相关总结,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下
    2021-01-01
  • vue子元素绑定的事件, 阻止触发父级上的事件处理方式

    vue子元素绑定的事件, 阻止触发父级上的事件处理方式

    这篇文章主要介绍了vue子元素绑定的事件, 阻止触发父级上的事件处理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Vue scoped及deep使用方法解析

    Vue scoped及deep使用方法解析

    这篇文章主要介绍了Vue scoped及deep使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08

最新评论