SOURCE

(function (global) {
    // 存储所有依赖,使用 Weakmap 保持键名对象的弱引用,浏览器会忽略 WeakMap 键名对象的引用关系
    const targetDepsMap = new WeakMap()
    let currentFn = () => { }

    // 收集依赖
    function track(target, key) {
        let depsMap = targetDepsMap.get(target)
        if (!depsMap) {
            depsMap = new Map()
            targetDepsMap.set(target, depsMap)
        }
        let deps = depsMap.get(key)
        if (!deps) {
            deps = new Set()
            depsMap.set(key, deps)
        }
        deps.add(currentFn)
    }

    function run(fn) {
        if (fn.options && fn.options.hooks) {
            fn.options.hooks(fn)
        } else {
            fn()
        }
    }

    // 触发依赖更新 watchEffect 回调
    function trigger(target, key) {
        const depsMap = targetDepsMap.get(target)
        if (depsMap) {
            const deps = depsMap.get(key)
            if (deps) {
                deps.forEach(fn => {
                    run(fn)
                })
            }
        }
    }
    const baseHandler = {
        get(target, key, receiver) {
            const res = Reflect.get(target, key)
            track(target, key)
            return (typeof res === 'object' && res !== null) ? reactive(res) : res
        },
        set(target, key, value, receiver) {
            const res = Reflect.set(target, key, value)
            trigger(target, key)
            return res
        },
    }

    function createEffect(fn, options = {}) {
        const effect = () => {
            currentFn = effect
            const res = fn()
            currentFn = () => { }
            return res
        }
        effect.options = options
        effect.raw = fn
        return effect
    }

    function reactive(target) {
        return new Proxy(target, baseHandler)
    }

    function watchEffect(fn, options) {
        const effect = createEffect(fn, options)
        effect()
        return effect
    }

    function computed(fn) {
        return {
            get value() {
                return fn()
            }
        }
    }

    function ref (value) {
        return reactive({
            value
        })
    }

    global.MVue = {
        reactive,
        watchEffect,
        computed,
        ref
    }
})(window);

(function test () {
    const { reactive, ref, computed, watchEffect } = MVue

    const person = reactive({
        name: 'Zhang San',
        age: 19,
    })
    const personInfo = computed(() => 'Name:' + person.name + ' Age:' + person.age)
    const count = ref(0)

    console.log('personInfo: ' + personInfo.value)
    console.log('count:' + count.value)

    watchEffect(() => {
        console.log(`watchEffect age: ${person.age}`)
    })

    setInterval(() => {
        person.age++
    }, 3000)
})()
console 命令行工具 X clear

                    
>
console