前言在Vue2的官方文档中,不知道大家有没有注意到,文档中有一个明确的表述:检测变化的注意事项检测变化的注意事项对象的问题添加未声明的属性删除属性varvm=newVue({data:{message:'hello'}})vm.message='hellovue'//`vm.message`是响应式的vm.describe='helloVue.js'//`vm.describe`它isnon-responsive//无响应deletevm.message的源码调试如下:通过调试可以看到data对象没有属性,delete属性无法转化为a响应式Vue。为什么Vue检测不到对象的变化?实例创建时无法检测到数据中不存在的属性由于Vue在初始化实例时会对属性进行getter/setter转换,所以属性必须存在于数据对象上,Vue才能将其转换为响应式。Vue不允许动态添加响应式属性,因此必须在初始化实例之前声明所有响应式属性的getter/setter。您只能跟踪一条数据是否已更改,而不能跟踪新的和删除的属性。数组的问题是当你直接用索引设置数组项时修改数组的长度varvm=newVue({data:{items:['a','b','c']}})vm.items[1]='x'//非响应式vm.items.length=2//非响应式视图没有变化为什么Vue检测不到数组的变化首先说一下结论:为什么Vue不提供对数组属性的监控,原因是:性能问题。即:性能成本与获得的用户体验收益不成正比。变化检测什么是变化检测?变化检测是跟踪状态,或者说数据的变化。一旦发生变化,必须更新视图。更改检测代码https://code.juejin.cn/pen/71...源码调试vuegithub地址注:本次调试使用v2.7.14版本。观察者源码我们发现,当检测数据为数组时,如果是数组,则判断是否支持__proto__,如果支持,则使用protoAugment覆盖原型。很明显,源代码对数组有单独的处理。为什么停止了数据检测呢?下面我们修改一段源码一探究竟。修改源码if(Array.isArray(value)){value.forEach((item,index)=>{defineReactive(value,index,item,undefined,shallow,mock);});//去掉之前的代码...}验证一下,我们再次调试后,让我们见证奇迹。点击按钮后,视图也会发生变化:这么简单的事情,为什么没有必要呢?更深入我们使用循环将数组数据塞入1000个元素,数据更新为:[0,1,2...,998,999]。然后加入set的时间也是ms级别的。更重要的是,console.log输出也很耗时。在其他问题上,我们将数组的每一项再次替换为一个Objcet,使其更接近该项。让temps=[]for(leti=0;i<1000;i++){temps.push({index:i,value:i+'',arr:[i]})}this.items=tempsthis.items[0]={index:0,value:999+'',arr:[999]}再次运行,页面更新也是ms级,没有一丝卡顿。此时,关于设置数组某值的研究暂时没有头绪。寻找修改数组长度的突破口,我们将数组长度改为10。setLen(){this.items.length=10}视图没有更新,原因是isArray()需要知道newArray。这时候,我们如果知道新的数据,就可以直接更新Array。之所以没有更新的问题,是因为Vue在拦截器中获取了Vue实例。而长度只是一个属性。这就是处理方法。通过以上操作无法拦截的源码如下:示意图如下:我们还原源码后发现Observer中的isArray没有响应。暂时没有新的突破,于是查了资料,果然有新的发现。有兴趣的挖矿者,可以继续研究,一起探讨,最后期待你的一键三连为什么vue不提供对数组属性的监控。ProxyVue3是基于JavaScriptProxy(代理)的Responsive。Proxy可以理解为在目标对象之前设置了一层“拦截”。外部对对象的访问必须先经过这一层拦截。因此,提供了一种机制来过滤和重写外部访问。但是Proxy对IE不友好。当vue3检测到使用IE(包括IE11)时,会自动降级为Object.defineProperty的数据监控系统API。当然Vue也给出了详细的解决方案:Vue.set(target,propertyName/index,value)")Vue.delete(target,propertyName/index)")Array.prototype.splice()总结JavaScript不够原生,这导致框架设计的局限性。(ES5的Object.defineProperty),导致Vue无法追踪数据变化。性能和用户体验。有时需要做出取舍。提供对阵列属性的监控
