Object.defineProperty这种方法的缺点是无法直接拦截数组(当然,也有点长),我们先看一个Object.defineProperty()的案例:
let obj = {}
let other = '';
Object.defineProperty(obj,'name',{
enumerable:true,//设置是否可枚举
configurable:true,//能不能删除这个属性
get(){//读取方法
console.log('--------');
return other;
},
set(val){//设置方法
other = val
}
// })
obj.name=789
console.log(obj.name);
let obj = {
other:'123',
get name(){
return this.other;
},
set name(val){
this.other = val
}
}
obj.name = '456'
console.log(obj.name);
// 对象的 setter和getter
// vue的数据劫持 (把所有属性都给成 get 和set方法)
function update(){
console.log('更新视图');
}
let data = {
name:'hj',
age:90,
adress:{
location:'昌平'
}
}
function observer(obj){
if(typeof obj !=='object') return obj;
for (let key in obj) {
deineReactive(obj,key,obj[key])
}
}
function deineReactive(obj,key,value){
observer(value)
Object.defineProperty(obj,key,{
get(){
return value
},
set(val){
if(val!==value){
observer(val)
update()
value = val
}
}
})
}
observer(data);
data.age = 82;
data.adress = [1,2,3];
let methods = ['push','slice','pop','sort','reverse','unshift'];
methods.forEach(method=>{
let oldMethod = Array.prototype[method];
Array.prototype[method] = function(){
update()
oldMethod.call(this,...arguments)
}
})
data.adress.push(4)
下面细讲一下 Proxy 代理方法:
function vue(){
this.$data ={
a:1
};
this.el = document.getElementById("app");
this._html = "";
this.observe(this.$data)
this.render()
}
vue.prototype.observe = function(obj){
var self = this;
this.$data=new Proxy(this.$data,{
get:function(target, key) {
return target[key]
},
set: function(target, key, newvalue){
target[key] = newvalue
self.render()
}
})
}
vue.prototype.render = function(){
this._html="i am" + this.$data.a;
this.el.innerHTML = this._html;
}
两种比较
defineProperty只能监听某个属性,不能全局对象监听,而proxy就可以,所以省去for-in;
defineProperty get中没有值;
,提高效率,可以监听数组,不需要再去单独对数组做操作