<!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>vuejs响应式</title>
</head>
<body>
<div class="wrapper">
<div class="text">0</div>
<div class="input">
<input id="input" type="text">
</div>
</div>
</body>
<script>
// 用一个全局变量存储被注册的副作用函数
let activeEffect
// effect用于注册副作用函数
function effect(fn) {
// 当调用effect注册副作用函数时,将副作用函数fn赋值给activeEffect
activeEffect = fn
// 执行副作用函数
fn()
}
// 存储副作用函数
const bucket = new WeakMap()
// 原始数据
const data = { text: 'hello word' }
// 对原始数据的代理
const obj = new Proxy(data, {
// 拦截读取操作
get(target, key) {
// 把副作用函数activeEffect添加到桶里去
track(target, key)
// 返回属性值
return target[key]
},
// 拦截设置操作
set(target, key, newVal) {
// 设置值
target[key] = newVal
// 把副作用函数从桶里去除并执行
trigger(target, key)
}
})
effect(() => {
document.querySelector('.text').innerHTML = obj.text
})
// 在get拦截函数内调用track函数追踪变化
function track(target, key) {
// 没有副作用函数,直接返回
if (!activeEffect) return target[key]
// 根据target从桶中取得depsMap,它也是夜歌Map类型:key --> effects
let depsMap = bucket.get(target)
// 如果不存在的depsMap,那么新建一个Map并与target关联
if (!depsMap) {
bucket.set(target, (depsMap = new Map()))
}
// 再根据key从deosMap中取得deps,他是一个Set类型
// 里面存储这所有与当前key相关联的副作用函数:effects
let deps = depsMap.get(key)
// 如果deps不存在,同样新建一个与Set并与key关联
if (!deps) {
depsMap.set(key, (deps = new Set()))
}
// 将副作用函数存储至桶中
deps.add(activeEffect)
}
// 在set拦截函数内调用trigger函数触发变化
function trigger(target, key) {
// 把副作用函数拿出来执行
const depsMap = bucket.get(target)
if (!depsMap) return
const effects = depsMap.get(key)
effects && effects.forEach(fn => fn())
}
let input = document.querySelector('#input')
input.addEventListener('input', function () {
obj.text = this.value
})
</script>
<style>
.wrapper {
position: absolute;
top: 30%;
left: 20%;
}
</style>
</html>
*来源于 Vue.js设计与实现 霍春阳 4.3 设计一个完善的响应系统
标签:target,depsMap,get,系统,响应,key,Vue3,副作用,函数 From: https://www.cnblogs.com/echohye/p/17019335.html