(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) })()