拦截器Object.defineProperty(对象,“属性名”,{对属性做一些规定})
- 作用:获取或新增一个属性,在该属性发生操作时,拦截操作,执行拦截器里规定的操作
Object.defineProperty(对象,"属性名",{
writable:true,//该属性是否可以修改,true可改变,默认false
configurable:true,//该属性的描述符是否可以改变,比如true时,该属性可删除,默认false不可删除
enumerable:true,//该属性是否可枚举,true可枚举,默认false
value://修改该属性的值,这里可以写任何值,包括数值,对象,函数,正则表达式等
set(val){return val+1}//当该属性被修改时,执行set后面的代码
get(){return }//当该属性被获取时,执行get后面的代码,属性的值改为return后面的值
})
- 注意
configurable定义为false时,后面就不能再改回true,并且之后再对该属性的拦截器定义除了value和writable其他都会报错
不写get时,只要有set的拦截,就会自动生成一个get拦截get(){return undefined}
set(val){}小括号里面的val值就是获取该属性的操作后获取到的值
writable为false时,value就会无效
当有set或get时,写writable和value就会报错
拦截器代理
proxy(target,handler)
- target目标对象
- handler也是一个对象,指定target的行为,就是写拦截器里面的代码
//写法一
let target = {
name: "gg",
age: 10
}
let handler = {
get: function(obj, k) {//obj实参对应的对象属性的集合数组,也就是target的数组形式,k拦截到的对象的键(属性)
console.log('getting '+k);
return obj[k]; // 不能用obj.k
},
set: function(obj, k, value) {//obj实参对应的对象属性的集合数组,k对象的键(属性),value改变属性值时的值
console.log('setting '+key);
obj[k] = value;
}
}
let p = new Proxy(实参对象名, 拦截器名)
p.name // 执行 handler.get
p.age = 25 // 执行 handler.set
//写法二,handler直接写在Proxy()里面
let p = new Proxy(实参对象名, {
get: function(obj, k) {
console.log('getting '+k);
return obj[k];
},
set: function(obj, k, value) {
console.log('setting '+key);
obj[k] = value;
}
})
- 注意点:
代理拦截里只写set也会自动生成一个get,但是这个get的返回值是拦截的属性值本身
代理拦截里不写set会自动生成一个set,里面有一句obj[k] = value,就是把修改的值赋值给对象的该属性
设置一个就可以对对象里的所有属性进行拦截。
proxy相当于一个构造函数,要用let 变量名 = new Proxy(target,handler),通过这个变量.属性名才会触发拦截,对象.属性名不会拦截
使用代理,实现数据的双向绑定
let i = document.querySelector("#sid");
let obj = {
sid:1
}
let proxy = new Proxy(obj,{
set(o,k,val){
o[k] = val;
i.value = val;
}
})
i.addEventListener("input",function(){
proxy.sid = this.value;
//这里也可以obj.sid=this.value(这个不会被拦截),但是最好用proxy,既然要拦截他每次改值都拦截,因为拦截之后除了赋值还能在get里面另外多做一些操作
})
同时绑定多个输入框
id:<input type="text" id="sid">
name:<input type="text" id="sname">
tel:<input type="text" id="tel">
<script>
let i = document.querySelectorAll("#sid");
let sn = document.querySelectorAll("#sname");
let tel = document.querySelectorAll("#tel");
let ipt = document.querySelectorAll("input");
let obj = {
sid:1,
sname:"张三",
tel:000
}
let proxy = new Proxy(obj,{
set(o,k,val){
//改变对象的值
o[k] = val;
//改变页面的值
switch(k){
case "sid":i.value = val;break;
case "sname":sn.value = val;break;
case "tel":tel.value = val;break;
}
}
})
ipt.forEach(function(value,index){
ipt[index].addEventListener("input",function(){
switch(ipt[index].id){
case "sid":proxy.sid = this.value;break;
case "sname":proxy.sname = this.value;break;
case "tel":proxy.tel = this.value;break;
}
})
})
</script>