Vue 3.0 reactive/effect
reactive.js:
import { isObject } from "../utils"; import { track, trigger } from "./effect"; export function reactive(target) { // 判断 target 类型 // 如果是基本类型,则不将其转化成响应式 if (!isObject(target)) return target; const proxy = new Proxy(target, { get(target, key, receiver) { const res = Reflect.get(target, key, receiver); // 收集依赖 track(target, key); return res; }, set(target, key, value, receiver) { const res = Reflect.get(target, key, value, receiver); // 触发依赖 trigger(target, key); return res; } }); return proxy; }
effect.js:
// 记录当前正在执行的副作用函数 let activeEffect; /** 难点 * 一个副作用函数可能依赖多个响应式数据 * 一个响应式数据更新可能会触发多个副作用函数 * 因此 targetMap 的结构是: * { * [target]: { * [key]: [] * } * } * 使用 WeakMap 是因为不需要手动删除不需要的依赖 */ const targetMap = new WeakMap(); export function effect(fn) { const effectFn = () => { try { activeEffect = effectFn; return fn(); } finally { // todo } } effectFn(); return effectFn; } export function track(target, key) { if (!activeEffect) return; let depsMap = targetMap.get(target); // 初始化时一定是不存在的 if (!depsMap) targetMap.set(target, (depsMap = new Map())); let deps = depsMap.get(key); // 同样,初始化的时候一定无值 if (!deps) depsMap.set(key, (deps = new Set())); deps.add(activeEffect); console.log(targetMap, key) } export function trigger(target, key) { const depsMap = targetMap.get(target); if (!depsMap) return; const deps = depsMap.get(key) if (!deps) return; deps.forEach(effectFn => { effectFn(); }); }
index.js(入口文件):
import { reactive } from "./reactive/reactive"; import { effect } from "./reactive/effect"; const observed = reactive({ count: 0 }); effect(() => { console.log(observed.count) })
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战