ヘラックスについて
Helux は、サービス インジェクションを促進し、レスポンシブな変更をサポートする新しいデータ フロー ソリューションです. その前身はconcent (Vue のような開発経験を持つ高パフォーマンスの状態管理フレームワーク) ですが、concent 自体は維持するためにクラスと関数と互換性がある必要があります。一貫性 文法、およびそのsetup
機能に対して、内部コードの量が多すぎます. 圧縮後、70
多くの kb があり API が露出しすぎて、学習の難易度が急激に増加します. もっと一致するためにDDD
、helux
、鼓励服务注入
. 支持响应式变更
_ 支持依赖收集
_
次の利点があります。
- 軽量、圧縮後2kb
- シンプルで、公開されている API は 7 つだけで、頻繁に使用されるのは
createShared
、useObject
、useSharedObject
、useService
の 4 つのインターフェースのみです。 - 高パフォーマンスの組み込みの依存関係コレクション
- レスポンシブ、レスポンシブ オブジェクトの作成をサポート、ビュー外のオブジェクトを変更すると、ビューが同期的に更新されます
useService
複雑なビジネス ロジックを簡単に制御するインターフェイスを備えたサービス インジェクションは、常に安定した参照を返すため、useCallback
依存関係の煩わしさを完全に回避できます。- ステータス プロモーション 0 が変更されるため、場所をプロモーション ステータス
useObject
に置き換えるだけで、他のコンポーネントと共有できます。useSharedObject
- forwordRef地獄を避けてください。組み込みモードは、親が子をドロップするときの転送におけるあいまいさと伝染の問題を簡単に
exposeService
解決します(世代間隔コンポーネントはレイヤーごとに転送する必要があります)ref
- ts フレンドリーで、100% ts で記述されており、オールラウンドな型のヒントを提供します
この gif と以下のすべての API は、オンラインの例 1と例 2に対応しています。経験をフォークして変更することを歓迎します。
なぜという名前なのか、helux
心の中でv3版としてconcent
開発したのですが、あまりにも変わってしまったので、concent
コレクションに頼る以外の機能を継承しておらず、開発したhel-microで生まれた作品でもありますヘルミクロのエコロジーに贅沢レベルの貢献を期待しているので、ヘルミクロと贅沢という言葉をまとめてみましたhelux
。
ようこそheluxに注目してください. 比較的新しいものですが, 私の使用シナリオではすでに不可欠な役割を果たしています. 今では hel-micro エコロジカル ダカンに参加しています. あなたが喜んでデータストリームになることを願っています.お選びください。
すぐに始めましょう
究極のシンプルさが helux の最大の利点です.次の 6 つの API を理解すれば、どんな複雑なシーンでも簡単に処理できます.最大の魅力は 2 つのインターフェイスにあります.以下の API の紹介を参照するか、オンラインのサンプル 1 とサンプル 2 のフォークuseSharedObject
にuseService
アクセスしてください.是非、体験してください。
useObject
useObject を使用する利点は 2 つあります。
- 1 複数の状態値を定義すると便利な場合は、useState の記述を少なくします
- 2 アンマウントの判断は内部で行われるため、非同期関数も安全に setState を呼び出すことができ、react での警告「アンマウントされたコンポーネントで SetState() を呼び出しました」エラーを回避できます。
// 基于对象初始化一个视图状态
const [state, setState] = useObject({a:1});
// 基于函数初始化一个视图状态
const [state, setState] = useObject(()=>({a:1}));
复制代码
useForceUpdate
現在のコンポーネント ビューを強制的に更新します。これは、いくつかの特別なシナリオでビューを更新するために使用できます
const forUpdate = useForceUpdate();
复制代码
createSharedObject
透過的に渡すことができる共有オブジェクトを作成します。useSharedObject
具体的な使用方法については、useSharedObject を参照してください。
// 初始化一个共享对象
const sharedObj = createSharedObject({a:1, b:2});
// 基于函数初始化一个共享对象
const sharedObj = createSharedObject(()=>({a:1, b:2}));
复制代码
createReactiveSharedObject
useSharedObject に透過的に渡すことができるレスポンシブ共有オブジェクトを作成する
// 初始化一个共享对象
const [reactiveObj, setState] = createReactiveSharedObject({a:1, b:2});
sharedObj.a = 111; // 任意地方修改 a 属性,触发视图渲染
setSharedObj({a: 111}); // 使用此方法修改 a 属性,同样也能触发视图渲染,深层次的数据修改可使用此方法
复制代码
createShared
函数签名
function createShared<T extends Dict = Dict>(
rawState: T | (() => T),
enableReactive?: boolean,
): {
state: SharedObject<T>;
call: <A extends any[] = any[]>(
srvFn: (ctx: { args: A; state: T; setState: (partialState: Partial<T>) => void }) => Promise<Partial<T>> | Partial<T> | void,
...args: A
) => void;
setState: (partialState: Partial<T>) => void;
};
复制代码
创建响应式的共享对象,当需要调用脱离函数上下文的服务函数(即不需要感知props时),可使用该接口替代createSharedObject
和createReactiveSharedObject
,该接口的第二位参数为是否创建响应式状态,为 true 时效果同 createReactiveSharedObject
返回的 sharedObj
const ret = createShared({ a: 100, b: 2 });
const ret2 = createShared({ a: 100, b: 2 }, true); // 创建响应式状态
// ret.state 可透传给 useSharedObject
// ret.setState 可以直接修改状态
// ret.call 可以调用服务函数,并透传上下文
复制代码
以下将举例两种具体的调用方式
// 调用服务函数第一种方式,直接调用定义的函数,配合 ret.setState 修改状态
function changeAv2(a: number, b: number) {
ret.setState({ a, b });
}
// 第二种方式,使用 ret.call(srvFn, ...args) 调用定义在call函数参数第一位的服务函数
function changeA(a: number, b: number) {
ret.call(async function (ctx) { // ctx 即是透传的调用上下文,
// args:使用 call 调用函数时透传的参数列表,state:状态,setState:更新状态句柄
// 此处可全部感知到具体的类型
// const { args, state, setState } = ctx;
return { a, b };
}, a, b);
}
复制代码
如需感知组件上下文,则需要useService
接口去定义服务函数,可查看 useService 相关说明
useSharedObject
函数签名
function useSharedObject<T extends Dict = Dict>(sharedObject: T, enableReactive?: boolean): [
SharedObject<T>,
(partialState: Partial<T>) => void,
]
复制代码
接收一个共享对象,多个视图里将共享此对象,内部有依赖收集机制,不依赖到的数据变更将不会影响当前组件更新
const [ obj, setObj ] = useSharedObject(sharedObj);
复制代码
useSharedObject
默认返回非响应式状态,如需要使用响应式状态,透传第二位参数为true即可
const [ obj, setObj ] = useSharedObject(sharedObj);
// now obj is reactive
setInterval(()=>{
state.a = Date.now(); // 触发视图更新
}, 2000);
复制代码
useService
函数签名
/**
* 使用用服务模式开发 react 组件:
* @param compCtx
* @param serviceImpl
*/
function useService<P extends Dict = Dict, S extends Dict = Dict, T extends Dict = Dict>(
compCtx: {
props: P;
state: S;
setState: (partialState: Partial<S>) => void;
},
serviceImpl: T,
): T & {
ctx: {
setState: (partialState: Partial<S>) => void;
getState: () => S;
getProps: () => P;
};
}
复制代码
它可搭配useObject
和useSharedObject
一起使用,会创建服务对象并返回,该服务对象是一个稳定的引用,且它包含的所有方法也是稳定的引用,可安全方法交给其它组件且不会破会组件的pros比较规则,避免烦恼的useMemo
和useCallback
遗漏相关依赖
搭配useObject
时
function DemoUseService(props: any) {
const [state, setState] = useObject({ a: 100, b: 2 );
// srv本身和它包含的方法是一个稳定的引用,
// 可安全的将 srv.change 方法交给其它组件且不会破会组件的pros比较规则
const srv = useService({ props, state, setState }, {
change(a: number) {
srv.ctx.setState({ a });
},
});
return <div>
DemoUseService:
<button onClick={() => srv.change(Date.now())}>change a</button>
</div>;
}
复制代码
搭配useSharedObject
时,只需替换useObject
即可,其他代码不用做任何改变
+ const sharedObj = createSharedObject({a:100, b:2})
function DemoUseService(props: any) {
- const [state, setState] = useObject({ a: 100, b: 2 );
+ const [state, setState] = useSharedObject(sharedObj);
复制代码
getState 和 getProps
因 state
和 props
是不稳定的,所以服务内部函数取的时候需从srv.ctx.getState
或srv.ctx.getProps
// 抽象服务函数
export function useChildService(compCtx: {
props: IProps;
state: S;
setState: (partialState: Partial<S>) => void;
}) {
const srv = useService<IProps, S>(compCtx, {
change(label: string) {
// !!! do not use compCtx.state or compCtx.state due to closure trap
// console.log("expired state:", compCtx.state.label);
// get latest state
const state = srv.ctx.getState();
console.log("the latest label in state:", state.label);
// get latest props
const props = srv.ctx.getProps();
console.log("the latest props when calling change", props);
// your logic
compCtx.setState({ label });
}
});
return srv;
}
export function ChildComp(props: IProps) {
const [state, setState] = useObject(initFn);
const srv = useChildService({ props, state, setState });
}
return (
<div>
i am child <br />
<button onClick={() => srv.change(`self:${Date.now()}`)}>
change by myself
</button>
<h1>{state.label}</h1>;
</div>
);
复制代码
exposeService
当孩子组件props上透传了exposeService
函数时,useService
将自动透传服务对象给父亲组件,是一种比较方便的逃离forwardRef
完成父调子的模式
import { ChildSrv, Child } from "./Child";
function App() {
// 保存孩子的服务
const childSrv = React.useRef<{ srv?: ChildSrv }>({});
const seeState = () => {
console.log("seeState", childSrv.current.srv?.ctx.getState());
};
return (
<div>
<button onClick={() => childSrv.current.srv?.change(`${Date.now()}`)}>
call child logic
</button>
<Child
unstableProp={`${Date.now()}`}
exposeService={(srv) => (childSrv.current.srv = srv)}
/>
</div>
);
}
复制代码