简体中文 | English
helux 是一个集atom
、signal
、依赖收集
、派生
、观察
为一体,支持细粒度响应式更新的状态引擎,支持所有类 react 框架(包括 react 18)
特性简介:
- 内置依赖追踪特性,基于最快的不可变 js 库limu开发,拥有超强性能
atom
支持任意数据结构且自带依赖收集功能, 无需拆分很细,天然对 DDD 领域驱动设计友好- 内置
signal
响应机制,实现 0 hook 编码 dom 粒度或块粒度的更新 - 内置
loading
模块,可管理所有异步任务的运行状态、并捕捉错误抛给组件、插件 - 内置
sync
系列 api,支持双向绑定,轻松应对表单处理 - 内置
reactive
响应式对象,支持数据变更直接驱动关联 ui 渲染 - 内置
define
系列 api,方便对状态模块化抽象,轻松驾驭大型前端应用架构 - 内置事件系统
- 支持可变派生,适用于当共享对象 a 部分节点变化需引起其他节点自动变化的场景,数据更新粒度更小
- 支持全量派生,适用于不需要对数据做细粒度更新的场景
- 全量派生、可变派生均支持异步任务
- 全量派生、可变派生除数据变更驱动执行外,还支持人工重新触发运行
- 支持中间件、插件系统,可无缝对接 redux 生态相关工具库
- 100% ts 编码,类型安全
为了方便用户理解
helux
核心逻辑,我们提供了how-helux-was-born项目用于辅助用户做 helux 源码调试。
使用 npm 命令npm i helux
安装helux
,然后调用atom
创建共享状态,调用useAtom
使用共享状态,that's all,你已接入helux
来提升局部状态为共享状态. ✨
import React from 'react';
+ import { atom, useAtom } from 'helux';
+ const [sharedState] = atom({ a: 100, b: { b1: 1 } });
function HelloHelux(props: any) {
- const [state, setState] = React.useState({ a: 100, b: { b1: 1, b2: 2 } });
+ const [state, setState] = useAtom(sharedState);
- const change = setState((prev) => ({ ...prev, b: { ...prev.b, b1: 100 } }));
+ const change = setState((draft) => { draft.b.b1 = 100 });
// 收集到当前组件依赖为 a,仅当 a 变更时才触发重渲染
return <div>{state.a}</div>;
}
以下是一些常见特性,更多特性可查阅文档里的Atom、Signal、依赖追踪、响应式、双向绑定、派生、观察、Action、模块化 等章节做深入了解
import { atom, useAtom } from 'helux';
const [numAtom] = atom(1); // { val: 1 }
function Demo() {
const [num, setAtom] = useAtom(numAtom); // num 自动拆箱
return <h1 onClick={setAtom(Math.random())}>{num}</h1>;
}
依赖追踪,组件渲染期间将实时收集到数据依赖
import { useAtom } from 'helux';
const [objAtom, setObj] = atom({ a: 1, b: { b1: 1 } });
// 修改草稿,生成具有数据结构共享的新状态,当前修改只会触发 Demo1 组件渲染
setObj((draft) => (draft.a = Math.random()));
function Demo1() {
const [obj] = useAtom(objAtom);
// 仅当 obj.a 发生变化时才触发重渲染
return <h1>{obj.a}</h1>;
}
function Demo2() {
const [obj] = useAtom(objAtom);
// 仅当 obj.b.b1 发生变化时才触发重渲染
return <h1>{obj.b.b1}</h1>;
}
信号响应,可将共享状态原始值直接绑定到视图
原始值响应
// 只会引起h1标签内部重渲染
<h1>{$(numAtom)}</h1>
// 格式化
<h1>{$(numAtom, num=>`hi helux ${num.val}`)}</h1>
<h1>{$(numAtom.val, num=>`hi helux ${num}`)}</h1>
块响应
import { block } from 'helux';
const [objAtom] = atom({ a: 1, b: { b1: 1 } });
const UserBlock = block(() => (
<div>
<h1>{objAtom.a}</h1>
<h1>{objAtom.b.b1}</h1>
</div>
));
// 依赖是 obj.val.a, obj.val.b.b1
<UserBlock />;
// 如使用 share 创建共享对象,则 UserBlock 实例的依赖是 obj.a, obj.b.b1
const [objAtom] = share({ a: 1, b: { b1: 1 } });
可变派生,响应共享状态自身某些节点变化,派生自身其他节点结果
import { share, mutate } from 'helux';
const [shared] = share({ a: 1, b: 0, c: 0 });
mutate(shared)({
changeB: (draft) => (draft.b = shared.a + 1),
changeC: (draft) => (draft.c = shared.a + 2),
});
响应其他共享状态某些节点变化,派生自身其他节点结果
import { share, mutate } from 'helux';
const [shared] = share({ a: 1 });
const [sharedB] = share({ b: 0, c: 0 });
mutate(sharedB)({
changeB: (draft) => (draft.b = shared.a + 1),
changeC: (draft) => (draft.c = shared.a + 2),
});
全量派生,响应其他共享状态某些节点变化,全量派生新结果
import { share, derive, deriveAtom, useDerived, useDerivedAtom } from 'helux';
const [shared] = share({ a: 1 });
const resultDict = derive(() => ({ num: shared.a + 100 })); // { num: number }
const resultAtom = deriveAtom(() => shared.a + 100); // 自动装箱:{ val: number }
const [result] = useDerived(resultDict); // { num: number}
const [result] = useDerivedAtom(resultAtom); // 自动拆箱:number
通过 watch 观察数据变化
主动定义依赖,首次不执行
import { watch } from 'helux';
// 仅观察到a变化才通知回调执行
watch(() => {
console.log('a change');
}, [shared.a]);
// shared任意节点变化就通知回调执行
watch(() => {
console.log('shared change');
}, [shared]);
设置 immediate=true
,立即执行,自动收集到依赖
watch(
() => {
console.log('a change', shared.a);
},
{ immediate: true },
);
欢迎入群了解更多,由于微信讨论群号 200 人已满,需加作者微信号或 qq 群号,再邀请你如helux & hel
讨论群(加号时记得备注 helux 或 hel)
小小鼓励,给予我们更多力量坚持做出更好的开源项目