arr数组怎么取值_记一次思否问答的问题思考:Vue为什么不能检测数组变动

8f1a4cee4557d81c677ae0ba87acf9f6.png

作者 | hfhan

来源 | https://segmentfault.com/a/1190000015783546

问题描述:Vue检测数据的变动是通过Object.defineProperty实现的,所以无法监听数组的添加操作是可以理解的,因为是在构造函数中就已经为所有属性做了这个检测绑定操作。

但是官方的原文:由于 JavaScript 的限制, Vue 不能检测以下变动的数组:

当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength

这句话是什么意思?我测试了下Object.defineProperty是可以通过索引属性来设置属性的访问器属性的,那为何做不了监听?

有些论坛上的人说因为数组长度是可变的,即使长度为5,但是未必有索引4,我就想问问这个答案哪里来的,修改length,新增的元素会被添加到最后,它的值为undefined,通过索引一样可以获取他们的值,怎么就叫做“未必有索引4”了呢?

既然知道数组的长度为何不能遍历所有元素并通过索引这个属性全部添加set和get不就可以同时更新视图了吗?

如果非要说的话,考虑到性能的问题,假设元素内容只有4个有意义的值,但是长度确实1000,我们不可能为1000个元素做检测操作。但是官方说的由于JS限制,我想知道这个限制是什么内容?各位大大帮我解决下这个问题,感谢万分。


面对这个问题,我想说的是,首先,长度为1000,但只有4个元素的数组并不一定会影响性能,因为js中对数据的遍历除了for循环还有forEach、map、filter、some等,除了for循环外(for,for...of),其他的遍历都是对键值的遍历,也就是除了那四个元素外的空位并不会进行遍历(执行回调),所以也就不会造成性能损耗,因为循环体中没有操作的话,所带来的性能影响可以忽略不计,下面是长度为10000,但只有两个元素的数组分别使用for及forEach遍历的结果:

var arr = [1]; arr[10000] = 1

可以看到结果非常明显,不过,如果for循环中不做操作的话两者速度差不多

其次,我要说的是,我也不知道这个限制是什么      (⇀‸↼‶)      ╮( •́ω•̀ )╭

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。数组的索引也是属性,所以我们是可以监听到数组元素的变化的

var arr = [1,2,3,4]

但是我们新增一个元素,就不会触发监听事件,因为这个新属性我们并没有监听,删除一个属性也是。

再回到题主的问题,既然数组是可以被监听的,那为什么vue不能检测vm.items[indexOfItem] = newValue导致的数组元素改变呢,哪怕这个下标所对应的元素是存在的,且被监听了的?

为了搞清楚这个问题,我用vue的源码测试了下,下面是vue对数据监测的源码:a47dff041a933a2b381fb3ef6e78f227.png

可以看到,当数据是数组时,会停止对数据属性的监测,我们修改一下源码:c85e31c7a0a8628bf6134d3413a1db98.png

使数据为数组时,依然监测其属性,然后在defineReactive函数中的get,set打印一些东西,方便我们知道调用了get以及set。这里加了个简单判断,只看数组元素的get,set879e6cb79896230d180ef5377ab4304b.png

然后写了一个简单案例,主要测试使用vm.items[indexOfItem] = newValue改变数组元素能不能被监测到,并响应式的渲染页面a4e51d2c1c54de4f673ffd9a39ed2572.png

运行页面913aa7fb2376ef2114c3265a9146b95c.png

可以看到,运行了6次get,我们数组长度为3,也就是说数组被遍历了两遍。两遍不多,页面渲染一次,可能多次触发一个数据的监听事件,哪怕这个数据只用了一次,具体的需要看尤大代码怎么写的。

就拿这个来说,当监听的数据为数组时,会运行dependArray函数(代码在上面图中get的实现里),这个函数里对数组进行了遍历取值操作,所以会多3遍get,这里主要是vue对data中arr数组的监听触发了dependArray函数。

当我们点击其中一个元素的时候,比如我点击的是3。8e11efefefe8022552a675d97e98b57e.png

可以看到会先运行一次set,然后数据更新,重新渲染页面,数组又是被遍历了两遍。

但是!!!数组确实变成响应式的了,也就是说js语法功能并不会限制数组的监测。

这里我们是用长度为3的数组测试的,当我把数组长度增加到9时。f8fc2a836cb1eb06d73f0c501ca862c6.png

可以看到,运行了18次get,数组还是被遍历了两遍,点击某个元素同理,渲染的时候也是被遍历两次。2294921e4b05cfc16fd6914f6ec783f3.png

有了上面的实验,我的结论是数组在vue中是可以实现响应式更新的,但是不明白尤大是出于什么考虑,没有加入这一功能,希望有知道的大佬们不吝赐教


2018-07-27补充

github上提问了尤大90de35abeda7f83a47802b13e0e40d08.png

dc31dabddf1198e64d72526dce597ed3.png

b7395db5660f816ebd37f209c43b86db.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556029.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 ref 对已渲染到页面的节点进行标记

一、字符串形式的 ref <input type"text" /*给标签打上标记 ipt */ ref"ipt" />拿到标记的节点&#xff0c;对其进行操作 handleClick () > {console.log(this);// 用 ref 标记了的标签&#xff0c;都会保存在 refs 里面console.log(this.refs…

JAVA之private修饰成员方法默认是final型的?

Java之private修饰成员方法默认是final型的&#xff1f; private修饰的成员方法默认是final型的&#xff1f; 用fianl声明的成员方法是最终方法&#xff0c;最终方法不能被子类覆盖&#xff08;重写&#xff09; 从表面上看这个命题是错误的&#xff0c;private访问修饰符修饰…

python高阶函数教学_Python 简明教程 --- 16,Python 高阶函数

对于那些快速算法&#xff0c;我们总是可以拿一些速度差不多但是更容易理解的算法来替代它们。—— Douglas Jones目录高阶函数一般以函数为参数。本节我们介绍Python 中三个方便的高阶函数&#xff0c;分别是&#xff1a;mapreducefilter如果你了解过分布式系统框架---Hadoop&…

react 组件传值

一、父传子 - 函数式组件 function Father (props) {const {money} props; // 解构render() {<div><Child getSonMoney{money}/></div>} }function Child (props) {return (<div><p>我爸爸现在有存款&#xff1a;${props.getSonMoney}</p&g…

深入理解static关键字

文章目录1、static存在的主要意义2、static的独特之处3、static应用场景4、静态变量和实例变量的概念5、静态变量和实例变量区别【重点常用】6、访问静态变量和实例变量的两种方式7、static静态方法8、static静态代码块9、static变量与普通变量区别10、静态内部类11、静态导包1…

kafka数据不丢失不重复_如何配置 KAFKA 使其消息不会丢失

不可靠的KAFKA这里的不可靠是指代KAFKA其设计之初就为高性能而设计&#xff0c;其是允许消息丢失的&#xff0c;但经过多个版本的升级之后&#xff0c;通过KAFKA的相关配置&#xff0c;我们可以将其作为可靠的队列(不丢消息的队列)。在本文里&#xff0c;不会具体列出要改哪个参…

聊聊 vue 生命周期

一、常用的常用的生命周期钩子&#xff1a; mounted: 发送 ajax 请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】 mounted() {console.log(vm 实例被挂载之后&#xff1a;mounted);this.timer setInterval(() > {...} }beforeDestroy: 清除定时器、解绑自定…

程序员你真的理解final关键字吗?

文章目录1、修饰类2、修饰方法3、修饰变量4、final变量修饰变量&#xff08;成员变量、局部变量&#xff09;4、1 final修饰成员变量&#xff1a;4、2 final修饰局部变量&#xff1a;5、final变量和普通变量的区别6、final与static的藕断丝连7、关于final修饰参数的争议前言 提…

axios vue 动态date_Web前端Vue系列之-Vue.js 实战

课程简介&#xff1a;课程目标&#xff1a;通过本课程的学习&#xff0c;让大家掌握Vue.js的进阶知识并在项目中应用。适用人群&#xff1a;具有一定vue开发基础的开发人员。课程概述&#xff1a;Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式Jav…

Static静态代码块以及各代码块之间的执行顺序

文章目录代码块的分类1、静态代码块&#xff08;也叫静态块、静态初始化块&#xff09;2、构造代码块&#xff08;也叫构造初始化块&#xff09;3、代码块&#xff08;又叫普通代码块、初始化块&#xff09;执行顺序的代码测试继承中各代码块的执行顺序前言 在Java中&#xff0…

vue 组件 - 非单文件组件

一、定义组件 const school Vue.extend({name: xuexiao, // ----------------------------> 指定组件在开发者工具中显示的名字template: // ----------------------------> 模板<div>... 此处是结构</div>,data() { // ---------------------------->…

matlab安装好 启动总是闪退_在Ubuntu16.04下安装MATLAB2017b

1. 前言最近在折腾Ubuntu系统的高端机子&#xff0c;matlab这家伙的交互和可视化太方便了&#xff01;于是想在Linux下安装matlab&#xff0c;在各个版本中&#xff0c;matlab2017的性价比是非常高的&#xff0c;因此选择安装介个。阅读了很多帖子&#xff0c;综合找到几个靠谱…

vue 脚手架

一、 脚手架 初始 全局安装脚手架 npm i -g vue/cli切换到项目根目录&#xff0c;使用 vue create 项目名称 创建项目使用 npm run serve | yarn serve 启动项目 如果中途卡顿 使用 npm 淘宝镜像 npm config set registry --> https://registry.npm.taobao.orgvue 隐藏了…

这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析

前言 package com.jvm.classloader;class Father2{public static String strFather"HelloJVM_Father";static{System.out.println("Father静态代码块");} }class Son2 extends Father2{public static String strSon"HelloJVM_Son";static{Syste…

bigdecimal js 判断等于0_为啥阿里禁用BigDecimal的equals方法做等值比较

BigDecimal&#xff0c;相信对于很多人来说都不陌生&#xff0c;很多人都知道它的用法&#xff0c;这是一种java.math包中提供的一种可以用来进行精确运算的类型。很多人都知道&#xff0c;在进行金额表示、金额计算等场景&#xff0c;不能使用double、float等类型&#xff0c;…

脚手架 - ref

被用来给元素或子组件注册引用信息&#xff08;id的替代者&#xff09;应用在 html 标签上获取的是真实 DOM 元素&#xff0c;应用在组件标签上的是组件实例对象 VueComponent{}使用方式 (1). 打标识 <!-- 给真实 DOM 元素打标识 --> <h1 ref"xxx">...&…

git提交到github总是要输入密码_GitHub不为人知的秘密

本来想叫《GitHub骚操作》的&#xff0c;发现相关的文章已经有很多&#xff0c;而且和我本章要讲的内容完全不同&#xff0c;所以就换了这个也算贴切的标题。起因之前写过一篇文章《VM Manager 插件分享》&#xff0c;事后我发现有个地方不对劲&#xff01;看之前文章标题大家应…

MyBatis中大于号以及小于号的表达方式

mybatis使用的是xml格式的文件。使用>和<号的时候&#xff0c;会存在与xml的标签的规范冲突。 1.场景还原 在实际项目中&#xff0c;有很多需求需要通过设定一个具体的时间段来搜索或过滤所需的数据&#xff0c;今天笔者就mybatis中时间比较涉及到的大于&#xff0c;小于…

脚手架 - props

一、props — 让组件接收外部传过来的数据 传递数据 <Example name"xxx"/>接收数据 // 1. 只接收 props: [name]// 2. 接收并限制类型 props: {name: String }// 3. 接收、限制类型、必要性、默认值 props: {name: {type: String, // 类型required: true, /…

mybatis plus当月数据查询_Springboot+mybatis(plus)+druid多数据源

前言:我不太喜欢AOP读自定义注解来切换数据源.因为如果我一个业务里需要同时查2个数据源的数据而又不想把这个业务拆成2个方法的时候,就比较麻烦了.所以我打算根据package来扫描注入不同的DataSource.可能是我搜索的姿势不太对 , 资料比较少.也会碰到不少坑.所以记录一下.正文:…