proxy对象顾名思义是对象的代理,对目标对象进行封装成代理对象,以达到读取、修改、查询目标对象属性等操作时起到拦截作用,对目标对象的默认操作进行重新定义。下面看一个例子:
let obj = {name: 'zhangsan', age: 20}
let objHandler = {
get: function(target,propKey){
return '您访问的属性: obj.' + propKey + ": " + target[propKey]
},
set: function(target,propKey,value){
if(propKey === 'name'){
typeof value !== 'string' ? console.log('你设置的值类型错误,请输入字符串类型') : target[propKey] = value
} else {
target[propKey] = value
}
}
}
let objProxy = new Proxy(obj, objHandler)
objProxy.name // "您访问的属性: obj.name: zhangsan"
objProxy.name = 222 // 你设置的值类型错误,请输入字符串类型
我们可以看到对obj对象封装成objProxy代理对象后,读取或者设置obj的name属性时,objProxy对象进行了拦截,改变了obj的默认行为,根据需要相应的重定义行为。这就给我们一个启发,vue的数据双向绑定是不是可以用proxy对象来实现呢?答案是肯定的,见代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>proxy实现数据双向绑定</title>
</head>
<body>
<div id='demotext'></div>
<button id="buttonclick">click</button>
<div><input type="text" id="inputtext"/></div>
<script>
let data = {
proxyText: ''
}
let demoText = document.querySelector('#demotext')
let inputText = document.querySelector('#inputtext')
let buttonClick = document.querySelector('#buttonclick')
let dataHandler = {
set: function(target, propKey, value){
target[propKey] = value
inputText.value = value
demoText.innerHTML = value
}
}
// 将data对象封装成代理对象
let dataProxy = new Proxy(data, dataHandler)
// 监听输入框的输入事件,将输入值赋值给代理对象实例,触发set方法拦截,
// 实现从输入框值到data对象proxyText属性值绑定
inputText.addEventListener('input',function(e){
dataProxy.proxyText = e.currentTarget.value
})
// js中动态改变data对象proxyText属性值,实现从data对象到input输入框的绑定
buttonClick.addEventListener('click',function(e){
dataProxy.proxyText = 'you have clicked me!'
})
</script>
</body>
</html>