vue2.x数组劫持原理的实现
接上篇Vue2.x对象劫持,继续来写数组劫持
实现原理:
1重新定义原生数组方法pushunshiftshiftpopsplicesortreverse因为这些方法可以修改原数组。
2拿到原生数组方法Object.create(Array.prototype)
3AOP拦截,再执行重写数组方法前,先执行原生数组方法
核心监听Observer代码
//把data中的数据都使用Object.defineProperty重新定义es5 //Object.defineProperty不能兼容ie8及以下vue2无法兼容ie8版本 import{arrayMethods}from'./array.js' import{ isObject,def }from'../util/index' //后续我可以知道它是不是一个已经观察了的数据__ob__ classObserver{ constructor(value){//仅仅是初始化的操作 //vue如果数据的层次过多需要递归的去解析对象中的属性,依次增加set和get方法 //value.__ob__=this;//我给每一个监控过的对象都增加一个__ob__属性 def(value,'__ob__',this); if(Array.isArray(value)){ //如果是数组的话并不会对索引进行观测因为会导致性能问题 //前端开发中很少很少去操作索引pushshiftunshift value.__proto__=arrayMethods; //如果数组里放的是对象我再监控 this.observerArray(value); }else{ //对数组监控 this.walk(value);//对对象进行观测 } } observerArray(value){//[{}] for(leti=0;i{ defineReactive(data,key,data[key]); }); } } functiondefineReactive(data,key,value){ observe(value);//递归实现深度检测 Object.defineProperty(data,key,{ configurable:true, enumerable:false, get(){//获取值的时候做一些操作 returnvalue; }, set(newValue){//也可以做一些操作 console.log('更新数据') if(newValue===value)return; observe(newValue);//继续劫持用户设置的值,因为有可能用户设置的值是一个对象 value=newValue; } }); } exportfunctionobserve(data){ letisObj=isObject(data); if(!isObj){ return } returnnewObserver(data);//用来观测数据 }
重写原生数组方法
//我要重写数组的那些方法7个pushshiftunshiftpopreversesortsplice会导致数组本身发生变化 //slice() letoldArrayMethods=Array.prototype; //value.__proto__=arrayMethods原型链查找的问题,会向上查找,先查找我重写的,重写的没有会继续向上查找 //arrayMethods.__proto__=oldArrayMethods exportconstarrayMethods=Object.create(oldArrayMethods); constmethods=[ 'push', 'shift', 'unshift', 'pop', 'sort', 'splice', 'reverse' ] methods.forEach(method=>{ arrayMethods[method]=function(...args){ constresult=oldArrayMethods[method].apply(this,args);//调用原生的数组方法 //pushunshift添加的元素可能还是一个对象 letinserted;//当前用户插入的元素 letob=this.__ob__; switch(method){ case'push': case'unshift': inserted=args; break; case'splice'://3个新增的属性splice有删除新增的的功能arr.splice(0,1,{name:1}) inserted=args.slice(2) default: break; } if(inserted)ob.observerArray(inserted);//将新增属性继续观测 returnresult; } })
工具方法定义如下:
/** * *@param{*}data当前数据是不是对象 */ exportfunctionisObject(data){ returntypeofdata==='object'&&data!==null; } exportfunctiondef(data,key,value){ Object.defineProperty(data,key,{ enumerable:false, configurable:false, value }) }
到此这篇关于vue2.x数组劫持原理的实现的文章就介绍到这了,更多相关vue2.x数组劫持内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!