当前位置: 首页 > Web前端 > HTML

Proxy代理数据拦截方法

时间:2023-03-27 22:41:44 HTML

proxyProxy对象用于创建一个对象的代理,从而实现对基本操作(如属性查找、赋值、枚举、函数调用等)的拦截和自定义。newProxy(target,handler)//target是proxy要包装的对象(可以是数组,函数,也可以是另一个Proxy)//handler是一个对象,通常有一个function作为属性,是用于自定义拦截行为的基本语法是:constp=newProxy(target,handler)主要方法有:handler.has()是in操作符的代理方法。handler.set()方法是设置属性值操作的捕手。handler.get()方法用于拦截对象的读取属性操作。handler.defineProperty()用于拦截对象上的Object.defineProperty()操作。handler.deleteProperty()方法用于拦截对对象属性的删除操作。handler.has()methodconstobj={name:'微芒神仙',occupation:'前端开发'}consthandler={has(target,key){//判断target中是否存在属性returnkey}}constp=newProxy(obj,handler)console.log(p.name)//魏曼不朽console.log(p.like)//undefinedconsole.log(p.occupation)//前端开发handler.get()methodconstobj={name:'微芒神仙',occupation:'前端开发'}consthandler={has(target,key){//判断target中是否存在该属性returnkey},get(target,key){if(keyintarget){returntarget[key]}else{returnnewReferenceError(key+'propertydoesnotexist')}}}constp=newProxy(obj,handler)console.log(p.name)//不朽微挂载console.log(p.like)//ReferenceError:like属性不存在console.log(p.occupation)//前端开发handler.set()方法constobj={name:'不朽微挂载',职业:'前端开发'}consthandler={set(target,key){if(keyintarget){returnReflect.set(...arguments)}thrownewReferenceEr复制代码ror(key+'propertydoesnotexist')}}constp=newProxy(obj,handler)p.like='programming'//UncaughtReferenceError:like属性不存在//console.log(p.like)p.occupation='Test'console.log(p.occupation)//测试handler.defineProperty()方法用于拦截Object.defineProperty()对对象的操作constobj={name:'魏漫不朽',configurable:真,可枚举:真,}consthandler={defineProperty(target,key,descriptor){console.log('property',key)returntrue;}}constp=newProxy({},handler)Object.defineProperty(p,'like',obj)//属性like也可以使用Reflect.definePropertyconstobj={name:'魏漫不朽',configurable:true,enumerable:true,}consthandler1={defineProperty(target,key,descriptor){console.log('property1',descriptor)returnReflect.defineProperty(target,key,descriptor)}}constp1=newProxy({},handler)Object.defineProperty(p1,'like',obj)//propertylikehandler.deleteProperty()方法主要是拦截对象的删除操作;constobj={name:'魏曼不朽',}consthandler={ddeleteProperty(target,key){console.log('delete'+key)}}constp=newProxy({},handler)deletep.name//删除名称//同时拦截Reflect.deletePropertyReflect.deleteProperty(obj,'name')Proxy.revocable代理有一个独特的静态方法,Proxy.revocable(target,handler)Proxy.revocable()方法可以用来创建一个可撤销的代理对象。该方法的返回值是一个对象,其结构为:{"proxy":proxy,"revoke":revoke}proxy代表新生成的代理对象本身,与一般方法new创建的代理对象没有区别Proxy(target,handler),除了可以撤销丢失。revoke方法可以撤销用它生成的代理对象,调用时不需要添加任何参数。constobj={name:'Immortality',}consthandler={}const{proxy,revoke}=Proxy.revocable(obj,handler)console.log(proxy.name)//Immortalrevoke()//值为closedandtheproxyisclosed,andrevokedtheproxyconsole.log(proxy.name)//UncaughtTypeError:illegaloperationattemptedonarevokedproxy应用场景Proxy实现格式校验场景:验证身份证、电话号码、姓名和emailaddressconstobj={certno:'420101198101012964',name:'魏漫不朽1',tel:'123456789',mail:'13@qq.com',}constvalidators={//验证证书编号certno(val){return/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val)},//查名字,只能是汉字name(val){return/^[\u0391-\uFFE5]+$/.test(val)},//查电话或手机号码tel(val){return/^1\d{10}$|^0\d{2,3}-?\d{7,8}$/.test(val)},//测试邮箱mail(){return/^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/.测试(值)}}constvalidatorType=(target,validator)=>{returnnewProxy(target,{_validator:验证器,set(target,key,value,proxy){letvalidator=this._validator[key](value)if(validator){returnReflect.set(target,key,value,proxy)}else{throwError(`将${key}的值设为${value},格式不正确`)}}})}constproxy=validatorType(obj,validators)proxy.certno='420101198101012964'proxy.name='WeimangImmortal1'//未捕获错误:设置name的值tomicroMountImmortal1,formatisincorrectproxy.tel='123456789'//UncaughtError:setthevalueoftelto123456789,formatisincorrectproxy.mail='13@qq.com'代理拦截私有属性使用代理拦截日常定义的私有属性,使其无法更改;一般以下划线开头;letobj={_id:'1234567890',name:'Immortal'}constp=newProxy(obj,{set(target,prop){if(prop[0]==='_'){throwError(`${prop}是私有属性`)}returnReflect.set(target,prop)}})p.name='Comeon'console.log(p.name)//Comeonp._id='123'console.log(p._id)//UncaughtError:_idisaprivateattributeReactive函数用来绑定引用数据类型,比如对象和数组等,实现响应式Proxy本质上是一个对象的劫持,所以即它不仅可以监控对象某个属性值的变化,还可以监控对象属性的增删改查。而reactive是vue3中数据劫持的核心。//判断是否是对象functionisObject(value){returnvalue!=null&&(typeofvalue==='object'||typeofvalue==='function')}functionreactive(obj){if(!isObject(obj)){returnobj}returnnewProxy(obj,{get(target,key){//TODO:收集依赖returnReflect.get(target,key)},set(target,key,value){//TODO:触发依赖returnReflect.set(target,key,value)}})}conststate=reactive({name:'鬼仙'})console.log(state)//代理对象//Proxy{:{…},:{…}}//:Object{name:"小仙"}//name:"小仙"//:Object{...}//:Object{get:get(target,key),set:set(target,key,value)//}//get:functionget(target,key)//set:functionset(target,key),价值)