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

Vue.js源码学习-Array

时间:2023-03-31 21:21:50 vue.js

双向绑定完整代码(https://github.com/mfaying/si...Object可以通过Object.defineProperty进行检测,但是数组还有其他改变数据的方法,比如push,pop等,是检测不到的,所以需要通过拦截原型来检测constarrayProto=Array。原型;exportconstarrayMethods=Object.create(arrayProto);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(method){constoriginal=arrayProto[method];Object.defineProperty(arrayMethods,method,{value:functionmutator(...args){constresult=original.apply(this,args);constob=this.__ob__;ob.dep.notify();返回结果;},enumerable:false,writable:true,configurable:true});});"push","pop","shift","unshift","splice","sort","reverse"这7个方法会改变数组数据,so拦截它。在拦截的方法中,我们可以触发依赖(ob.dep.notify()),也可以通过original.apply(this,args)方法调用数组原型。收集依赖数组也是在“get”中收集的,比如获取ob中的数组constob={a:[]};必须使用ob.a来获取,会触发get,可以在这个Time中找到依赖来收集。那么依赖应该存放在哪里呢?与Object不同的是,数组依赖存储在Observer中。这是因为在“get”中需要收集依赖(childOb.dep.depend()),在Observer转换响应式数据时能够获取到依赖,从而在拦截数组原型方法(ob.depend)时通知依赖。dep.notify()),把依赖存放在Observer中比较合适。当然不是直接获取依赖,通过//def是defineProperty的封装,函数签名是def(obj,key,val,enumerable)def(value,"__ob__",this);在私有属性__ob__中设置了Observer的实例,所以无论是依赖收集还是通知,都是通过Observer实例__ob__上的dep属性来操作的。同时,__ob__也成为了判断数据是否响应式的依据,具有该属性的数据是响应式的。数组中的对象如果数组中有对象,如何保证对象也对应呢?由于push、unshift、splice这三个数组方法会增加新的数组元素,我们只需要将新插入的元素转换为响应式数据即可。从“./util”导入{def};constarrayProto=Array.prototype;导出constarrayMethods=Object.create(arrayProto);[“push”,“pop”,“shift”,“unshift”,“拼接”,"sort","reverse"].forEach(function(method){constoriginal=arrayProto[method];def(arrayMethods,method,functionmutator(...args){constresult=original.apply(this,args)};constob=this.__ob__;letinserted;switch(method){case"push":case"unshift":inserted=args;break;case"splice":inserted=args.slice(2);break;}如果(inserted)ob.observeArray(inserted);ob.dep.notify();returnresult;});});参考《深入浅出Vue.js》完整代码(https://github.com/mfaying/si...