记录vue3源码学习01.Effect 简单实现响应式

98 阅读1分钟
<div id="app"> defatul content </div>
<script>
    let activeEffect
    const data = { text: 'hello' }
    const bucket = new WeakMap()
    const obj = new Proxy(data, {
        get (target, key) {
            // 判断effec方法执行的时候 有没有给activeEffect赋值 , 没有就直接返回数据
            if (!activeEffect) return target[key]
            // 判断之前对这个对象target 绑定过数据没有 有就跳过到下一步 没有就初始化 
            /* 
            此时bucket的数据结构为
            '{text:"hello"}':new Map() 也就是下面那样
            '{text:"hello"}':{}
            deps的数据结构则就是 { } 
            */
            let depsMap = bucket.get(target)
            if (!depsMap) {
                bucket.set(target, (depsMap = new Map()))
            }
            // 判断 有没有deps 有的话就掉过下一步  没有就绑定
            /* 此时的数据结构为

                '{text:"hello"}':{key:[]}
            */
            let deps = depsMap.get(key)
            if (!deps) {
                depsMap.set(key, (deps = new Set()))
            }
            // deps添加副作用函数
            /* 
                此时的数据结构为
                  '{text:"hello"}':{key:[()=>{
                     document.getElementById('app').innerHTML = target.key
                  }]}
             */
            deps.add(activeEffect)
            return target[key]
        },
        set (target, key, value) {
            target[key] = value
            // 拿出一个map对象此时为数据结构为
            /* 
            depsMap = {
                key : [
                    ()=>{
                        //执行副作用
                    }
                ]
            }
            
            */
            let depsMap = bucket.get(target)
            // 没有就返回
            if (!depsMap) return
            // 从depsMap 对象里面 拿出 对应的key
            const effects = depsMap.get(key)
            // 此时的effct内部的数据结构为
            /* 
                effects = [
                    ()=>{
                        // 副作用
                    }
                ]
             */
            console.log(effects);
            effects && effects.forEach(fn => fn());
        }
    })

    // 用一个全局变量存储被注册的副作用函数
    // effect 函数用于注册副作用函数
    function effct (fn) {
        // 当调用 effect 注册副作用函数时,将副作用函数 fn 赋值给activeEffect
        activeEffect = fn
        // 执行副作用函数
        fn()
    }
    effct(() => {
        document.getElementById('app').innerHTML = obj.text
    })

    function track (target, key) {

    }

    setTimeout(() => {
        obj.text = 'new world12312312'
    }, 1000)


</script>