createReactive
将普通对象转换为响应式对象,支持属性变化监听。
函数签名
typescript
function createReactive<T extends Record<string, any>>(
target: T,
deps: CreateReactiveDeps
): Reactive<T>
interface CreateReactiveDeps extends ReactiveDeps {
/** 创建代理对象 */
createProxy: <T extends Record<string, any>>(target: T, deps: ReactiveDeps) => T
/** 获取变化路径 */
getChangePath: (target: any, property: string | symbol) => string[]
}前置依赖
依赖参数
| 参数名 | 类型 | 说明 |
|---|---|---|
deps.subscribers | Set<(...args: any[]) => void> | 订阅者集合,用于存储所有监听器 |
deps.notify | () => void | 通知函数,当状态变化时调用所有订阅者 |
deps.subscribe | (listener: () => void) => () => void | 订阅函数,添加监听器并返回取消订阅函数 |
deps.dispose | () => void | 清理函数,清除所有订阅者 |
deps.createProxy | <T>(target: T, deps: ReactiveDeps) => T | 代理创建函数,返回包装了响应式逻辑的代理对象 |
deps.getChangePath | (target: any, property: string | symbol) => string[] | 路径获取函数,返回属性变化的路径数组 |
环境要求
- Proxy: 现代浏览器和 Node.js 环境支持
bash
# Node.js 环境已内置支持
# 浏览器环境需要现代浏览器(IE11+ 或其他现代浏览器)参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
target | T | 是 | 要转换为响应式的目标对象 |
deps | CreateReactiveDeps | 是 | 环境依赖,包含所有需要的函数 |
返回值
| 类型 | 说明 |
|---|---|
Reactive<T> | 响应式对象,扩展了原始对象类型并添加响应式方法 |
工作原理
- 代理包装:使用
Proxy创建目标对象的代理,拦截属性访问和修改 - 订阅管理:维护订阅者集合,支持添加和移除监听器
- 变化检测:监听对象属性的
set和deleteProperty操作 - 通知机制:当属性发生变化时,自动调用所有订阅者函数
- 嵌套支持:支持嵌套对象的响应式变化追踪
- 动态属性:支持动态添加和删除对象属性
响应式对象特性:
- 保持原始对象的所有属性和方法
- 添加
subscribe()、notify()、dispose()等响应式方法 - 透明代理,不改变原始对象的使用方式
- 支持嵌套对象的深度响应式
异常
| 错误类型 | 触发条件 | 错误信息 |
|---|---|---|
TypeError | 目标对象不支持代理 | Cannot create proxy with a non-object as target |
完整示例
typescript
import { createReactive } from 'zcw-shared/reactive/createReactive'
// 准备目标对象
const state = {
count: 0,
name: '响应式对象',
nested: { value: 100 }
}
// 创建响应式对象
const reactiveState = createReactive(state, {
subscribers: new Set(),
notify: () => {
console.log('状态发生变化!')
},
subscribe: (listener) => {
reactiveState.subscribers.add(listener)
return () => reactiveState.subscribers.delete(listener)
},
dispose: () => reactiveState.subscribers.clear(),
createProxy: (target, deps) => new Proxy(target, {
get(target, property) {
// 响应式方法直接返回
if (property === 'subscribe' || property === 'notify' ||
property === 'dispose' || property === 'subscribers') {
return deps[property as keyof typeof deps]
}
return target[property as keyof typeof target]
},
set(target, property, value) {
const oldValue = target[property as keyof typeof target]
;(target as any)[property] = value
deps.notify()
return true
},
deleteProperty(target, property) {
if (property in target) {
delete target[property as keyof typeof target]
deps.notify()
return true
}
return false
}
}),
getChangePath: (target, property) => [String(property)]
})
// 使用响应式对象
console.log(reactiveState.count) // 0
// 添加监听器
const unsubscribe = reactiveState.subscribe(() => {
console.log('当前状态:', reactiveState)
})
// 修改属性会触发通知
reactiveState.count = 1 // 输出: 状态发生变化!
reactiveState.name = '新名称' // 输出: 状态发生变化!
reactiveState.nested.value += 10 // 输出: 状态发生变化!
console.log(reactiveState.count) // 1
// 取消订阅
unsubscribe()
// 清理所有订阅
reactiveState.dispose()实际应用场景
typescript
// 简单状态管理
const appState = createReactive({
user: { name: '', age: 0 },
settings: { theme: 'light', language: 'zh' }
}, reactiveDeps)
// 组件状态监听
const unsubscribe = appState.subscribe(() => {
updateUI(appState)
})
// 数据驱动更新
function updateUI(state) {
userNameElement.textContent = state.user.name
themeClass = state.settings.theme
}响应式系统是现代前端框架的核心特性,通过 createReactive 可以轻松实现数据驱动的界面更新。