当前位置: 首页 > Web前端 > vue.js

关于vue中如何监听数组变化

时间:2023-03-31 17:12:05 vue.js

前言前段时间学习了vue中响应式数据的原理(并做了vue响应式原理的学习笔记)。其实就是通过Object.defineProperty来控制getter和setter,使用观察折纸方式做的响应式设计。然后数组有一系列的操作方法,这些方法不会触发数组的getter和setter方法。那么数组的响应式设计在vue中是如何实现的呢……那就一起来学习吧~源码部分https://github.com/vuejs/vue/blob/dev/src/core/observer/array.js从哪里开始学习第一步?Emmmm...我觉得还是有必要先把Vue中数据响应的原理说清楚,这样才能更好的理解Vue中如何检测数组的变化。因此,您可以在网上找到它。下载文章,结合源码阅读,相信你就明白了。推荐一个我以前看过的博客,还有我自己看完后写的学习记录,哈哈。Vue响应式原理Vue的双向绑定原理和实现不错,先来看看这个。哈哈!从图入手,我们先看下图,先了解一下Vue中实现的思路,这样我们接下来看源码实现的时候,就会一目了然。看到这张图想一想,你是不是有个大概的了解呢?首先通过__proto__指针判断浏览器是否支持改写数组的7种方法,然后根据是否支持__proto__将改写后的数组指向数组的原型。是不是很简单!!!我们先看看源码,了解了实现原理,再来看一下源码。看源码的主要目的是为了更深入地理解作者是如何实现的。也可以看看优秀的代码编码方法来学习。我会在下面的代码块中写一些解释!//https://github.com/vuejs/vue/blob/dev/src/core/observer/array.js//def方法是基于Object.defineProperty封装的一层方法,很简单,我会放在下面代码贴出来了,免得大家找不到。import{def}from'../util/index'//保存原始数组原型对象constarrayProto=Array.prototype//原型连接,将arrayMethods的原型指向Array.prototypeexportconstarrayMethods=Object.create(arrayProto)constmethodsToPatch=['push','pop','shift','unshift','splice','sort','reverse']methodsToPatch.forEach(function(method){//缓存本地方法constoriginal=arrayProto[方法]def(arrayMethods,method,functionmutator(...args){varargs=[],len=arguments.length;while(len--)args[len]=arguments[len];constresult=original.apply(this,args)//原数组方法执行结果constob=this.__ob__//这个__ob__是Observe的一个实例~~~~letinsertedswitch(method){case'push':case'unshift':inserted=argsbreakcase'splice':inserted=args.slice(2)break}if(inserted)ob.observeArray(inserted)//如果数组改变,再次调用observeArray//通知改变ob.dep.notify()//返回结果})})这是关于Observe的代码代码:varObserver=functionObserver(value){this.value=value;this.dep=newDep();这个.vmCount=0;def(值,'__ob__',这个);//这里会看到在Eachobjectdata中会绑定一个Observe的实例,所以上面代码中的this.__ob__就是thisif(Array.isArray(value)){//这里判断是否是数组类型的数据,如果是这样,去observeArrayif(hasProto){protoAugment(value,arrayMethods);}else{copyAugment(值,arrayMethods,arrayKeys);}this.observeArray(值);//这里是处理数组类型的数据,如下}else{this.walk(value);}};下面是observeArray的实现:Observer.prototype.observeArray=functionobserveArray(items){for(vari=0,l=items.length;i