MicroVue框架搭建Part1——基本目录结构MicroVue框架搭建Part3——$Mount方法实现microVue框架搭建Part4——Render渲染前概述使用Object.defineProperty()实现数据代理数据代理实现原理概述代表数据模型对象嵌套对象数组类型数据模型,数组内置方法触发后会改变代理数据data:{name:"小明",age:10,address:"家庭住址",info:{IDCard:"身份证号码",school:"学校名称",obj:{name:"sddd"}},list:[{a:1,b:2}]}数据代理实现-代理单个数据/***@param{*}需要代理的关键字段-字符串类型*@param{*}proxyObj代理对象-对象类型*@param{*}originObject原始数据object-对象类型*@returns*/functionproxyKey(key,proxyObj,originObject){Object.defineProperty(proxyObj,key,{configurable:true,//允许增删代理对象的key,同时同步原数据get:function(){returnoriginObject[key];},设置:函数(val){return(originObject[key]=val);},});返回代理对象;}//代码实践constprpxyObj={};letdata={a:20,b:30}window.test=proxyKey("a",prpxyObj,data)代理数组方法目的:修改数组对象的原型链,改变数组内置方法的执行体,如push方法和pop方法。Object.defineProperty()中的value属性:对应proxy属性value可以是任何有效的JavaScript值(数字、对象、函数等),即你可以控制返回的结果。constarrProxyFunc=newArray();/***obj:代理对象*proxyFunction:要代理的数组方法*/functionproxyArrayFunctionCall(obj,proxyFunction){Object.defineProperty(obj,proxyFunction,{enumerable:true,configurable:true,//允许删除内容ofproxydatavalue:function(...args){//映射Array原型链上的方法,constarrProxyFunc=arrayProtoType[proxyFunction];//将this改为指向constresult=arrProxyFunc.apply(this,args);返回结果;},});}/***array:需要被代理的数组方法——它的原型链会被完全覆盖*/functionproxyArray(array){//创建代理对象——新的数组原型链完全覆盖之前的原型链constobj={eleType:"Array",pop(){},push(){}};//代理自定义方法proxyArrayFunctionCall(obj,"pop",);proxyArrayFunctionCall(obj,"push");/***覆盖原有的原型链——从而实现数组方法的代理*完全覆盖之前数组的原型链,不再支持内置的数组方法,只能使用obj对象提供的方法*/array.__proto__=obj;返回数组;}//代码调试constarr=[];窗口.arr=arr;window.test=代理数组(arr);可以看到不管arr的原型链都被我们修改了,从而实现了对数组内置方法的代理。我们在实现数据代理的时候会利用这一点来实现Vue框架中的数据代理实现。对象嵌套对象的数据代理:在proxyObject()方法中可以看到实现数组类型数据代理的代码片段:proxyArray()命名空间:getNameSpace(),该方法是为了保证数据在nestedobjectsintheobject来源不会错。比如代理obj对象下的test,代理keynum时,其在原始数据中的值应该是obj.test.num。所以,在实现它的代理时,命名空间是字符串obj.testletobj={a:10,test:{num:20}}Object.getOwnPropertyNames():返回一个指定对象的所有自身属性的属性名(一个属性数组,包括不可枚举的属性但不包括符号值作为名称)。我们在实现代理数组方法时使用了Object.getOwnPropertyNames,将所有的内置方法映射到数组的原型链上。/***数据代理*/constarrayProtoType=newArray();functiongetNameSpace(nameSpace=null,key=null){if(nameSpace&&!key){returnnameSpace;}elseif(key&&!nameSpace){返回键;}else{return`${nameSpace}.${key}`;}}functiongetObjectKey(obj){returnObject.keys(obj);}/****@param{*}待代理的关键字段*@param{*}proxyObj代理对象*@param{*}originObject原始数据对象*@returns*/functionproxyKey(key,proxyObj,originObject){Object.defineProperty(proxyObj,key,{configurable:true,get:function(){returnoriginObject[key];},set:function(val){return(originObject[key]=val);},});返回代理对象;}/***代理对象*@param{}选项*@returns*/functionproxyObject(vm,option,nameSpace){letproxyObj={};常量公关oxyAllKey=getObjectKey(选项);for(leti=0;i
