SOURCE

console 命令行工具 X clear

                    
>
console
// 用于收集依赖
const bucket = new WeakMap()

// 创建一个中间值去记录effect函数
let activeEffect

const effect = function (fn) {
    activeEffect = fn
    // 第一次一定要执行一次fn
    fn()
}

// 设计追踪函数
function trackFunc(target, key) {
    // 如果当前activeEffect是空的,说明无法收集依赖
    if (!activeEffect) {
        return
    }

    // 每一个target在bucket中都有一个Map类型,去记录我当前的变量的key对应的effect函数
    let depsMap = bucket.get(target)
    if (!depsMap) {
        // 如果没有就创建新的
        bucket.set(target, (depsMap = new Map()))
    }
    // 创建完成后去找对应的key存储的effect函数
    let deps = depsMap.get(key)
    // 如果没有呢,就继续创建
    if (!deps) {
        depsMap.set(key, (deps = new Set()))
    }
    // 将当前激活的effect函数存储进去
    deps.add(activeEffect)
}

// 执行依赖,也就是在变量赋值后执行effect函数
function trigger(target, key) {
    // 读取depsMap
    const depsMap = bucket.get(target)
    if (!depsMap) {
        return
    }
    const deps = depsMap.get(key)

    deps && deps.forEach(fn => fn())
}

// reactive的实现就很简单了
function reactive(data){
    return new Proxy(data,{
        get:(target,key)=>{
            const value=target[key]
            trackFunc(target,key)

            return value
        },
        set:(target,key,newValue)=>{
            target[key]=newValue
            trigger(target,key)
        }
    })
}

const $app=document.querySelector('#app')

const nameObj=reactive({
    name:'akimixu'
})

const ageObj=reactive({
    age:100
})

effect(()=>{
    console.log("执行effect函数")
    $app.innerText=`hello ${nameObj.name},are you ${ageObj.age} years old?`
})


setTimeout(()=>{
    nameObj.name="徐秋实"
},1000)

setTimeout(()=>{
    ageObj.age=123
},5000)
<!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="app"></div>
</body>

</html>
#app{
    width: 200px;
    height: 100px;
    background-color: #ffffff;
}