Vue2.X和Vue3.0数据响应原理变化的区别
defineProperty定义对象的属性,只不过属性里的get和set实现了响应式。
常用:
- value属性值
- get
- set
- writeable是否可写
- enumrable可遍历
Vue2.X数据响应原理
创建页面,实现延时2s修改对象的值。
LearnVue3.0
defineProperty实现:
functionvue(){ this.$data={ a:1 }; this.el=document.getElementById('app'); this._html=""; this.observe(this.$data); this.render(); } vue.prototype.observe=function(obj){ letself=this; letvalue; for(letkeyinobj){ value=obj[key]; if(typeofvalue==='object'){ this.observe(value); }else{ Object.defineProperty(this.$data,key,{ get:function(){ returnvalue; }, set:function(newvalue){ value=newvalue; self.render() } }) } } } vue.prototype.render=function(){ this._html="Iam"+this.$data.a; this.el.innerHTML=this._html; }
在Chrome中console运行,结果页面显示:Iam444
针对数组特性化处理:
letarraypro=Array.prototype; //为什么要create再次创建对象,create是深拷贝,不影响之前的arraypro letarrayob=Object.create(arraypro); //定义哪些方法触发更新 letarr=["push","pop","shift"]; //arr里的方法,既能保持原有方法,又能触发更新 //装饰者模式 arr.forEach(function(method,index){ //对自己的push方法重写 arrayob[method]=function(){ letret=arraypro[method].apply(this,arguments); //self.render(); console.log('检测到数组变化,触发更新'); returnret; } });
在Chrome中console运行示例:
letarr=[]; arr.__proto__=arrayob; arr.push(1);
结果显示:
Vue3.0数据响应原理
Vue3.0数据响应原理
创建页面,实现延时2s修改对象的值。代码同上。
Proxy实现:
functionvue(){ this.$data={ a:1 }; this.el=document.getElementById('app'); this._html=""; this.observe(this.$data); this.render(); } vue.prototype.observe=function(obj){ letself=this; this.$data=newProxy(this.$data,{ get:function(target,key){ returntarget[key]; }, set:function(target,key,newvalue){ target[key]=newvalue; self.render(); } }) } vue.prototype.render=function(){ this._html="Iam"+this.$data.a; this.el.innerHTML=this._html; }
在Chrome中console运行,结果页面显示:Iam444
为什么改用Proxy
- defineProperty只能监听某个属性,不能对全对象监听
- 可以省去forin循环提升效率
- 可以监听数组,不用再去单独的对数组做特异性操作
Proxy还能做什么
校验类型
functioncreateValidator(target,validator){ returnnewProxy(target,{ _validator:validator, set(target,key,value,proxy){ if(target.hasOwnProperty(key)){ letvalidator=this._validator[key]; if(validator(value)){ returnReflect.set(target,key,value,proxy); }else{ throwError('typeerror'); } } } }) } letpersonValidator={ name(val){ returntypeofval==='string'; }, age(val){ returntypeofval==='number'&&val>18; } } classperson{ constructor(name,age){ this.name=name; this.age=age; returncreateValidator(this,personValidator); } }
在Chrome中console运行示例:
lettmp=newperson('张三',30);
结果显示:
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。