<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
vue3兼容性只到ie11,如果监测到vue3无法兼容,会自动优雅降级到vue2
<script>
// vue3中的响应式原理,利用Proxy对象对数据拦截
// 如何避免重复代理
const toProxy = new WeakMap() //形如 obj:observed
const toRow = new WeakMap() //形如 observed:obj
function isObject(obj){
return typeof obj === 'object' || obj === null
}
function reactive(obj){
if(!isObject(obj)){
return
}
// 查找缓存
if(toProxy.has(obj)){
return toProxy.get(obj)
}
// 传入的obj就是代理对象,此时不用反复代理
if(toRow.has(obj)){
return obj
}
const observed = new Proxy(obj,{
// 属性的增删改查都涉及到了
get(target,key,receiver){
// 优雅的获取值
const res = Reflect.get(target,key,receiver)
console.log(`获取${key}:${res}`);
// 运行时递归,相比于初始化递归,性能较好
return isObject(res) ? reactive(res) : res
},
set(target,key,val,receiver){
// 返回bool
const res = Reflect.set(target,key,val,receiver)
console.log(`设置${key}:${res}`);
return res
},
deleteProperty(target,key){
const res = Reflect.deleteProperty(target,key)
console.log(`删除${key}`);
return res
},
})
// 缓存
toProxy.set(obj,observed)
toRow.set(observed,obj)
return observed
}
const data = {foo:'foo',bar:{a:1},arr:[1,2,3]}
const react = reactive(data)
// 1获取
// react.foo
// 2设置已存在属性
// react.foo = 'fooooooo'
// 3设置不存在属性
// react.name = 'zhongwuhuang'
// 4嵌套对象设置
react.bar.a = 10
react.bar.a
// 操作数组
// react.arr[0] = 10
// react.arr
// 时候是否缓存成功
// console.log(react === reactive(data));
</script>
</body>
</html>