最基本的 reactive 实现
实现一个最简单的 reactive 函数,能够:
- 使用
Proxy拦截对象的读取和修改操作 - 在读取属性时调用
track收集依赖 - 在修改属性时调用
trigger触发更新
核心代码实现
Section titled “核心代码实现”1. reactive 函数
Section titled “1. reactive 函数”reactive 函数接收一个普通对象,返回一个 Proxy 代理对象:
import { track, trigger } from './effect'
export function reactive<T extends object>(target: T): Texport function reactive(target: object) { const proxy = new Proxy(target, { get(target, key) { // 收集依赖 track(target, key) // 返回对象的相应属性值 const result = Reflect.get(target, key) return result }, set(target, key, value) { // 触发更新 trigger(target, key) // 设置对象的相应属性值 const result = Reflect.set(target, key, value) return result }, })
return proxy}2. track 和 trigger 函数
Section titled “2. track 和 trigger 函数”目前只是打印日志,后续会实现真正的依赖收集和触发更新:
export function track(target: object, key: unknown) { console.log(`target ${JSON.stringify(target)} 依赖收集:${key}属性被读取了`)}
export function trigger(target: object, key: unknown) { console.log(`target ${JSON.stringify(target)} 触发更新:${key}属性被修改了`)}为什么使用 Reflect?
Section titled “为什么使用 Reflect?”在 Proxy 的 handler 中,推荐使用 Reflect 而不是直接操作 target:
// 不推荐get(target, key) { return target[key]}
// 推荐get(target, key) { return Reflect.get(target, key)}原因:
Reflect方法的返回值更合理(如Reflect.set返回布尔值表示是否成功)Reflect可以正确处理this指向问题- 与 Proxy 的 trap 方法一一对应,语义更清晰
可以阅读 Reflect 原理笔记 结合理解。
export function reactive<T extends object>(target: T): Texport function reactive(target: object) { // ...}使用函数重载可以保留原对象的类型信息,让 TypeScript 能够正确推断返回值类型。
创建一个简单的 HTML 文件测试:
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>basic-reactive</title> </head> <body> <script type="module"> import { reactive } from '../dist/reactivity.esm.js'
const raw = { count: 1 } const proxyRaw = reactive(raw)
// 读取属性,触发 track console.log(proxyRaw.count) // 输出: target {"count":1} 依赖收集:count属性被读取了 // 输出: 1
// 修改属性,触发 trigger proxyRaw.count++ // 输出: target {"count":1} 依赖收集:count属性被读取了 // 输出: target {"count":2} 触发更新:count属性被修改了 </script> </body></html>这个最基本的 reactive 实现展示了响应式系统的核心思路:
- 使用
Proxy拦截对象的读写操作 - 在
get中调用track收集依赖 - 在
set中调用trigger触发更新 - 使用
Reflect确保操作的正确性
虽然功能还不完整,但已经搭建好了响应式系统的基本框架。