美文网首页让前端飞
Vue不能观察到数组length的变化

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

作者: 88b61f4ab233 | 来源:发表于2018-11-23 22:19 被阅读5次

由于 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
}
//前端全栈学习交流圈:866109386
//面向1-3经验年前端开发人员
//帮助突破技术瓶颈,提升思维能力

那么vue提供了一些解决方法

使用内置的Vue.$set

让数组显式的进行某个索引的观察 Vue.set(array, indexOfItem, newValue)

实际上是调用了

Object.defineProperty(array, indexOfItem, {
 enumerable: true,
 configurable: true,
 get() { },
 set(newVal) { }
})
//前端全栈学习交流圈:866109386
//面向1-3经验年前端开发人员
//帮助突破技术瓶颈,提升思维能力

这样可以手动指定需要观察的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 的限制,Vue 不能检测以下变动的数组: 当你利用索引直接设置一个项时,例如:vm.i...

  • 【vue】为什么要使用Vue.$set(target,key,v

    vue中不能检测到数组和对象的两种变化: 1.数组长度的变化 vm.arr.length = 4 2,数组通过索引...

  • 关于 vue 不能 watch 数组变化 和 对象变化的解决方案

    博客地址:关于 vue 不能 watch 数组变化 和 对象变化的解决方案 vue 监听数组和对象的变化 vue ...

  • Vue学习

    $set 1.vue不能检测以下变动的数组 (不能通过索引或者length改变数组) 通过索引值改变数组 d...

  • 某公司前端面试题

    1.Vue双向绑定的原理。 2、数组变化有哪些情况下不能视图不能同步更新 对于数组的变化: a、利用索引...

  • 数组

    var names = ["one", "two"];1、获取数组的长度:数组名.length;2、数组长度可变化...

  • vue之$set

    vue之$set 原因 由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此我们还是有一...

  • 如何监听数组的length变化?

    前面实现的数组劫持,实际上还有一点不完美的地方:当数组进行push操作时,length会自动增加1,如何监听到长度...

  • Vue 检测数据变化

    1.检测数组 由于javascript的限制,Vue不能检测到下面数组的变化:直接索引设置元素,如vm.item[...

  • Vue中常见的坑

    Vue无法追踪数组的变化

网友评论

    本文标题:Vue不能观察到数组length的变化

    本文链接:https://www.haomeiwen.com/subject/jzbsqqtx.html