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

news/2024/7/10 2:13:51 标签: vue

由于 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方法来进行隐式观察。


http://www.niftyadmin.cn/n/1301137.html

相关文章

敏捷开发之XP极限编程

敏捷方法论有一个共同的特点,那就是都将矛头指向了“文档”,它们认为传统的软件工程方法文档量太“重”了,称为“重量级”方法,而相应的敏捷方法则是“轻量级”方法。正是因为“轻量级”感觉没有什么力量,不但不能够有…

scrum与Xp的区别

相同点:SCRUM和XP都是 敏捷开发 的方法论,都体现了快速反馈,强调交流,强调人的主观能动性等基本原则,而且多数“最佳实践活动”都互相适用。 不同点:Scrum 非常突出Self-Orgnization(管理 &…

iOS使用第三方AppleID账号

当我们需要用第三方AppleID开发的时候,一般是自己开发的产品需要让合作方公司来推广或者运营。 当这样的情况的时候,合作方会给出大概以下(打包参数沙箱.txt)的参数,和下图右边的文件(打包参数沙箱.txt、内…

Vue插件打包与发布的方法示例

插件打包与发布 插件功能开发完成后,若需要发布到公共组件库中(例如:npmjs),需要对插件进行打包并发布,简单说明一下这个过程,以插件名 dialog 为例 1、创建 dialog 目录,并进入 2…

Http的body变空格的问题解决方案

最近在做iOS的内购功能,需要把内购的凭证转化为base64传给服务器,服务器再去AppStore的接口进行二次验证。 这中间有一个问题是base64编码的字符串里有“号”这样的字符,传到服务器上“号”字符就变成空格字符了。 原因是我们在进行http请求…

智能指针—从auto_ptr说起

文章转载自&#xff1a;https://blog.csdn.net/k346k346/article/details/81478223 auto_ptr 是STL中智能指针家族的成员&#xff08;auto_ptr、unique_ptr_、share_ptr、week_ptr&#xff09;之一&#xff0c;由C98引入&#xff0c;定义在头文件<memory>。其功能和用法类…

Struts1框架

今天来看一下Struts1的相关知识&#xff0c;其实Struts现在是出名的&#xff0c;每个Web开发者都会知道的&#xff0c;也是现在比较流行的框架&#xff0c;下面就来看一下我们为什么要用Struts框架呢&#xff1f; 摘要 1&#xff0e;建立在mvc这种好的模式上的&#xff0c;Stru…

基于Vue实现拖拽效果

效果图 分清clientY pageY screenY layerY offsetY的区别 在我们想要做出拖拽这个效果的时候&#xff0c;我们需要分清这几个属性的区别&#xff0c;这几个属性都是计算鼠标点击的偏移值&#xff0c;我们需要对其进行了解才可以继续实现我们的拖拽效果 clientY 指的是距离可视…