什么是Proxy
1. 概念
- ES6新特性,翻译为代理,从它的字面意思来看差不多就是说用它来代理某些操作
它的功能跟设计模式中的代理模式有些相似,简单的实现了控制外部对对象访问的功能 - 可以理解成在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
- 核心优点:
可以交由它来处理一些非核心逻辑,从而可以让对象只需关注于核心逻辑,达到关注点分离,降低对象复杂度等目的
2. 基本语法
let pro = new Proxy(target, handler);
参数解释:
- target
是用Proxy包装的被代理对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。 - handler
是一个对象,其声明了代理target 的一些操作,其属性是当执行一个操作时定义代理的行为的函数。 - pro
代理后的对象。当外界每次对 p 进行操作时,就会执行 handler 对象上的一些方法。Proxy共有13种劫持操作,handler代理的一些常用的方法有如下几个:- get:读取
- set:修改
- has:判断对象是否有该属性
- construct:构造函数
案例展示:
//用Proxy来定义一个对象的get和set,作为一个基础demo
let obj = {};
let handler = {
//读取属性的值时,实际上执行的是 handler.get() :在控制台输出信息,并且读取被代理对象 obj 的属性。
get(target, property) {
console.log(`${property} 被读取`); //name 被设置为 张三丰
return property in target ? target[property] : 3;
},
//设置属性值时,实际上执行的是 handler.set() :在控制台输出信息,并且设置被代理对象 obj 的属性的值
set(target, property, value) {
console.log(`${property} 被设置为 ${value}`); //age 被读取
target[property] = value;
}
}
let pro = new Proxy(obj,handler);
pro.name="张三丰";
console.log(pro.age); // 3
3. 双向绑定的实现
用demo说话才是最好的,上代码:
<body>
<dic id="app">
<input id="input" type="text">
<div>
输入的内容为:
<span id="tit"></span>
</div>
<input type="button" id="btn" value="添加到list">
<ul id="list">
</ul>
</dic>
</body>
let obj = {};
let newObj = new Proxy(obj,{
get:function(target,key,receiver){
console.log(getting+key);
return Reflect.get(target,key,receiver);
},
set:function(target,key,value,receiver){
console.log(target,key,value,receiver);
if(key == "text"){
$("#input").value = value;
$("#tit").innerHTML = value;
}
return Reflect.set(target,key,value,receiver);
}
});
$("#input").addEventListener("keyup",function(e){
newObj.text=e.target.value;
})
function $(str){
if(str.charAt(0)=="#"){
return document.getElementById(str.substr(1));
}else if(str.charAt(0)=="."){
return document.getElementsByClassName(str.substr(1));
}else{
return document.getElementsByTagName(str.substr(1))
}
}
添加todolist列表,先把数组渲染到页面
// 渲染list列表
let Render = {
// 初始化
init:function(arr){
const htmlDom = document.createDocumentFragment();
for(let i in arr){
const liDom = document.createElement("li");
liDom.textContent=arr[i];
htmlDom.appendChild(liDom);
}
$("#list").appendChild(htmlDom);
},
addList:function(val){
const liDom = document.createElement("li");
liDom.textContent=val;
$("#list").appendChild(liDom);
}
}
创建新的Proxy,实现list的添加
// 创建新的 Proxy,实现List的添加
const arr = [];
// 数组监听
const newArr = new Proxy(arr,{
get:function(target,key,receiver){
return Reflect.get(target,key,receiver);
},
set:function(target,key,value,receiver){
console.log(target,key,value,receiver);
if(key !== "length"){
Render.addList(value);
}
return Reflect.set(target,value,key,receiver);
}
});
// 初始化
window.onload=function(){
Render.init(arr);
}
$("#btn").addEventListener("click",function(){
newArr.push(parseInt(newObj.text));
})