cn hx data Reactive API - bradwoo8621/hx GitHub Wiki
响应式 API 参考
reactive(target, options?)
创建响应式根对象。返回一个代理,在任意嵌套修改时触发变更事件。
function reactive<T extends object>(
target: T,
options?: ReactiveOptions
): ReactiveRoot & T
const state = reactive({ count: 0, items: ['a', 'b'] });
// state 同时是 ReactiveRoot 和 { count, items }
选项
interface ReactiveOptions {
onChanged?: (event: ValueChangedEvent) => void;
}
const state = reactive(
{ count: 0 },
{
onChanged(event) {
console.log('内置监听器:', event.pathToRoot);
}
}
);
onChanged 回调在每次变更时调用。它等效于 ERO.on(state, '*', listener),但在其他已注册监听器之前触发。
ERO — ExposedReactiveObject
ERO 是提供公共 API 的单例静态类。所有方法都是静态的。
import { ERO } from '@hx/data';
ERO.on(obj, path, listener)
在某个路径上订阅变更。
ERO.on(
obj: any, // 任意响应式对象(根或嵌套)
path: string, // "*" | "path.*" | "path"
listener: (event: ValueChangedEvent) => void
): void
const state = reactive({ user: { name: '张三', age: 30 } });
// 全局:捕获所有
ERO.on(state, '*', (e) => {
console.log(`[全局] ${e.pathToRoot}: ${e.oldValue} → ${e.newValue}`);
});
// 分支:捕获 user 子树
ERO.on(state, 'user.*', (e) => {
console.log(`[user] ${e.pathToRoot}: ${e.oldValue} → ${e.newValue}`);
});
// 精确:仅 user.name 变更
ERO.on(state, 'user.name', (e) => {
console.log(`[name] ${e.oldValue} → ${e.newValue}`);
});
ERO.off(obj, path, listener)
取消订阅。
const listener = (e: ValueChangedEvent) => console.log(e.pathToRoot);
ERO.on(state, 'count', listener);
state.count = 1; // 触发
ERO.off(state, 'count', listener);
state.count = 2; // 不触发
路径必须与注册时完全一致。
ERO.emit(obj, key, oldValue, newValue)
手动触发变更事件,不修改对象本身。
ERO.emit(state, 'count', 0, 99);
// 'count' 或 'count.*' 上的监听器会触发
ERO.isReactiveRoot(obj)
ReactiveRoot 类型守卫。
const root = reactive({ x: 1 });
ERO.isReactiveRoot(root); // true
ERO.isReactiveRoot(123); // false
ERO.isReactiveObject(obj)
任意响应式对象(根或嵌套)的类型守卫。
const root = reactive({ user: {} });
const user = root.user;
ERO.isReactiveObject(root); // true
ERO.isReactiveObject(user); // true(嵌套对象也被代理)
ERO.isReactiveObject(123); // false
ERO.rootOf(obj)
从任意嵌套后代获取根对象。
const root = reactive({ user: { address: { city: '北京' } } });
const address = root.user.address;
ERO.rootOf(address) === root; // true
ERO.parentOf(obj)
获取父对象。如果是根对象则返回 undefined。
const root = reactive({ user: { name: '张三' } });
const user = root.user;
ERO.parentOf(user) === root; // true
ERO.parentOf(root) === undefined; // true
ERO.pathToRoot(obj)
从根到该对象的绝对路径。
const root = reactive({ user: { address: { city: '北京' } } });
const city = root.user.address;
ERO.pathToRoot(city); // 'user.address'
ERO.pathToParent(obj)
从父级到该对象的路径片段。
const root = reactive({ user: { name: '张三' }, items: ['a', 'b'] });
ERO.pathToParent(root.user); // 'user'
ERO.pathToParent(root.items); // 'items'
ERO.pathOf(obj, andPath?)
解析绝对路径。支持相对路径遍历。
const root = reactive({
user: { name: '张三', address: { city: '北京' } },
age: 30
});
const address = root.user.address;
// 当前对象的绝对路径
ERO.pathOf(address); // 'user.address'
// 相对路径:./ 深入
ERO.pathOf(address, './city'); // 'user.address.city'
// 相对路径:../ 向上
ERO.pathOf(address, '../name');// 'user.name'
// 多级向上
ERO.pathOf(address, '../../age'); // 'age'
// 绝对路径:/ 重置到根
ERO.pathOf(address, '/age'); // 'age'
ERO.getValue(obj, path)
获取值。适用于普通对象和响应式对象。对响应式对象支持相对/绝对路径。
// 普通对象
ERO.getValue({ a: { b: 1 } }, 'a.b'); // 1
// 响应式对象 + 相对路径
const state = reactive({ user: { name: '张三', age: 30 } });
const user = state.user;
ERO.getValue(user, './name'); // '张三'
ERO.getValue(user, '/user/age'); // 30
ERO.setValue(obj, path, value)
设置值。在响应式对象上触发事件。自动创建中间路径。
const state = reactive({ user: { name: '张三' } });
ERO.setValue(state, 'user.name', '李四'); // 触发事件
ERO.setValue(state, 'user.address.city', '北京'); // 自动创建中间对象
相对路径:
const address = state.user.address; // 上面创建的
ERO.setValue(address, './zip', '100001');
ERO.setValue(address, '../name', '王五');
ERO.setValueSilent(obj, path, value, mode?)
静默设置,不触发事件。直接操作底层普通对象。mode 默认为 mute-all:
mute-all(默认):完全不触发事件mute-leaf:仅叶子节点静默;中间路径创建仍触发事件loud:触发所有变更事件,等价于ERO.setValue
const state = reactive({ user: { name: '张三' } });
// 完全静默(默认模式)
ERO.setValueSilent(state, 'user.name', '李四');
ERO.setValueSilent(state, 'user.name', '李四', 'mute-all');
// 仅叶子节点静默;中间路径创建仍触发事件
ERO.setValueSilent(state, 'user.newField', 'value', 'mute-leaf');
ERO.revoke(obj)
撤销代理。返回不带代理的普通 JavaScript 对象。
const reactiveObj = reactive({ x: 1 });
const plain = ERO.revoke(reactiveObj);
plain.x = 2; // 不触发事件
reactiveObj.x = 3; // 触发事件(代理仍在生效)
ERO.fake()
创建桩响应式对象,任何访问都会打印错误日志。用于测试或占位场景。
const fake = ERO.fake<{ name: string }>();
fake.name; // console.error: "Always returns undefined, when getter[name] called..."
fake.name = 1; // console.error: "Always returns true, when setter[name] called..."
ERO.loosePathOf(obj?, andPath?)
类似 pathOf,但对 null/undefined 输入返回 undefined(不抛异常)。
ERO.loosePathOf(null); // undefined
ERO.loosePathOf(someObj); // 等同于 ERO.pathOf(someObj)