ES6——Proxy
今天的学习先从一个简单需求说起:
假设后端传给前端数据XXX,我们必须将数据XXX渲染到页面上,但是由于后端的数据
不停的改变,我们能否实现前端的页面的数据XXX跟着后端数据一起同步改变呢?
这里我们用input输入框输入的不同结果来模拟后端不停数据的改变;
用一个div模拟前端数据的展示;
<input id='input' type="text" name="" > //注意:仅作为模拟后端数据改变使用
<div id='div'></div> //前端渲染的页面
我们先试着写一下:
var oData = { //后端数据oData;
value: '后端数据:XXX'
};
input.oninput = function(){ //当触发input事件时,后端数据改变:
oData.value = this.value;
}
function upData (){ //更新视图,前端数据相应改变
div.innerText = oData.value;
}
upData();
我们来看一下效果:
效果还不错,但是当输入值改变后端数据时,结果却不尽人意
当后端数据发生改变时,无法同步更新视图,原因就是:输入时肯定在页面加载完成之后,所以该方法不理想
那么有没有一种功能可以监听oData的变化呢?接下来就看看ES6为我们提供的Proxy的数据劫持功能吧:
//同样的需求:
const oData = { //后端数据oData;
value: '后端数据:XXX'
};
input.oninput = function(){ //当触发input事件时,后端数据改变:
oData.value = this.value;
}
function upData (){ //更新视图,前端数据相应改变
div.innerText = oData.value;
}
//Proxy用法:
const oProxyData = new Proxy(oData, { //用一个对象代理oData对象的拦截;
get(target, key, receiver){ //拦截get行为:(参数:所拦截对象,属性名,代理对象)
// console.log(target, key, receiver);
// return target[key]; //返回对象的属性值;
return Reflect.get(target, key);
//通过Reflect直接获取对象中的某个值;
},
set(target, key, value, receiver){ //拦截set行为(参数:所拦截对象,属性名,设置的属性值,代理对象)
//console.log(target, key, value, receiver)
Reflect.set(target, key, value);
//通过Reflect直接创建对象中的某个值;
upData(); //监听后端数据改变时,进行视图更新;
}
});
input.oninput = function(){
//当触发input事件时,由于后端的oData代理给了oProxyData,
//所以直接更改oProxyData.value:
oProxyData.value = this.value;
}
我们再来看一下效果:
显而易见,通过ES6的Proxy完成了视图的同步更新工作(当然ES5中的Object.defineProperty() 也可实现数据劫持)
Proxy原理为代理,这里可以译为有它代理某些操作,译为“代理器”
我们再看一段代码:
var proxy = new Proxy({}, {
get: function(target, property) {
return 35;
}
});
let obj = Object.create(proxy);
obj.time // 35
Proxy对象是obj对象的原型,obj对象本身并没有time属性,所以根据原型链,会在proxy对象上读取该属性,导致被拦截
Proxy的原理:
Proxy用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层拦截,外部所有的访问必须先通过这层拦截,因此提供了一种机制(可以对外部访问进行过滤和修改)
Proxy的主要作用:
拦截和监视外部对对象的访问
降低函数或类的复杂度
在复杂操作前对操作进行校验或对所需资源进行管理
实现私有变量、抽离效验模块、访问日志、预警和拦截、过滤操作、中断代理等操作中都可见到Proxy的身影,甚至能为vue3背后的内部相应系统提供动力
Proxy植入代理模式的思想,以简洁易懂的方式控制对外部对象的访问,但是目前由于兼容性的问题,用法不够广泛,相信解决兼容问题后必定大放异彩