Proxy
对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
先看一个简单的示例:
var proxyObj = new Proxy(
{a:123,b:456},
{
get:function(target,key){
//target是目标对象,key是目标对象的键,当读取代理对象proxyObj的属性的时候,会进入到这里
return target[key]+"hello"
},
set:function(target,key,value){
//value是设置代理对象某个属性的值的内容,当设置代理对象proxyObj的属性的时候,会进入到这里
target[key] = value + "s"
}
}
)
复制代码进入控制台,试着读取和设置代理对象的属性,可以看到:
vue3的响应式就是基于Proxy
一步步实现的,这里咱们实现一个最简单的响应式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="test"></div>
<button onclick="changeText()">修改数据</button>
<script>
var obj,data={
text:"hello world"
}
function changeText(){
obj.text = obj.text + Math.random()
}
function renderText(){
console.log("renderText",obj.text)
document.querySelector("#test").innerHTML = obj.text
}
var effectFn = []
function effect(data,fn){
obj = new Proxy(data,{
get(target,key){
console.log(fn)
if(effectFn.indexOf(fn) == -1){
effectFn.push(fn)
}
console.log("读取了")
return target[key]
},
set(target,key,newValue){
target[key] = newValue
if(effectFn){
console.log("响应了")
effectFn.forEach(fn=>{fn()})
}
}
})
}
effect(data,renderText)
renderText()
</script>
</body>
</html>
新建html文件,将这段代码复制进去保存,打开html,点击按钮,可以看到,页面上的数据跟着点击事件自动重新渲染了。