Skip to content

Commit

Permalink
add effects API
Browse files Browse the repository at this point in the history
  • Loading branch information
huang2002 committed Jan 31, 2019
1 parent 4ac55bf commit c565bcd
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 41 deletions.
14 changes: 11 additions & 3 deletions src/core/HNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,22 @@ export type HProps<P extends object = any> = {
children: unknown[];
});

export type HCallback<P extends object = any, S extends Store = Store, C extends Store = Store, T = unknown> =
(this: HNode<P, S, C>, props: HProps<P>, store: S, context: C) => T;

export type EffectCallback<P extends object = any, S extends Store = Store, C extends Store = Store> =
HCallback<P, S, C, HCallback<P, S, C, void> | void>;

export interface HDesc<P extends object = any, S extends Store = Store, C extends Store = Store> {
defaultProps?: Partial<P>;
defaultStore?: Partial<StoreType<S>>;
storeHandlers?: PartialHandlers<StoreHandlers<S>, S>;
effects?: EffectCallback<P, S, C>[];
state?: Array<keyof StoreType<S>>;
context?: Array<keyof StoreType<C>>;
init?: (this: HNode<P, S, C>, props: HProps<P>, store: S, context: C) => void;
render: (this: HNode<P, S, C>, props: HProps<P>, store: S, context: C) => unknown;
clear?: (this: HNode<P, S, C>, props: HProps<P>, store: S, context: C) => void;
init?: HCallback<P, S, C, void>;
render: HCallback<P, S, C, unknown>;
clear?: HCallback<P, S, C, void>;
catch?: (this: HNode<P, S, C>, err: any, props: HProps<P>, store: S, context: C) => unknown;
}

Expand All @@ -52,6 +59,7 @@ export interface HNode<P extends object = EleProps, S extends Store = Store, C e
nodes?: Node[];
active: boolean;
evMap?: EventMap;
eff?: HCallback<P, S, C, void>[];
err?: unknown;
}

Expand Down
4 changes: 3 additions & 1 deletion src/core/HUI.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HProps as _HProps, HDesc as _HDesc, HNode as _HNode } from "./HNode";
import { HProps as _HProps, HDesc as _HDesc, HNode as _HNode, HCallback as _HCallback, EffectCallback as _EffectCallback } from "./HNode";
import { registry, define, HType as _HType } from "./registry";
import { _assign, _Infinity, _requestAnimationFrame } from "../utils/refCache";
import { Store as _Store, createStore, HandlerMap as _HandlerMap, Setter as _Setter, SetterRecord as _SetterRecord, StoreType as _StoreType, StoreHandlers as _StoreHandlers, PartialHandlers as _PartialHandlers, EmptyStore as _EmptyStore } from "./Store";
Expand Down Expand Up @@ -43,6 +43,8 @@ HUI.cmp = compare;
export namespace HUI {

export type HProps<P extends object = any> = _HProps<P>;
export type HCallback<P extends object = any, S extends _Store = _Store, C extends _Store = _Store, T = unknown> = _HCallback<P, S, C, T>;
export type EffectCallback<P extends object = any, S extends _Store = _Store, C extends _Store = _Store> = _EffectCallback<P, S, C>;
export type HDesc<P extends object = any, S extends _Store = _Store, C extends _Store = _Store> = _HDesc<P, S, C>;
export type HNode<P extends object = any, S extends _Store = _Store, C extends _Store = _Store> = _HNode<P, S, C>;

Expand Down
17 changes: 11 additions & 6 deletions src/core/initComponent.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
import { HNode } from "./HNode";
import { HNode, HCallback, HProps } from "./HNode";
import { Store } from "./Store";
import { supply } from "../utils/helpers";
import { _Boolean } from "../utils/refCache";

export const initComponent = function initCom(hNode: HNode<any>, store: Store) {
export const initComponent = function initCom<P extends object = any, S extends Store = Store, C extends Store = Store>(hNode: HNode<P, S, C>, store: S) {

const { props, ctx } = hNode,
desc = hNode.desc!,
{ defaultProps, defaultStore, storeHandlers, state, context, init } = desc;
{ defaultProps, defaultStore, storeHandlers, state, context, init, effects } = desc;

if (defaultProps) {
supply(props, defaultProps);
supply(props, defaultProps as Partial<HProps<P>>);
}

hNode.sto = store;
if (defaultStore) {
store.setSome(defaultStore);
}
if (state) {
hNode.sto.bind(hNode, state);
hNode.sto.bind(hNode as unknown as HNode, state);
}
if (storeHandlers) {
store.handleSome(storeHandlers);
}

if (context) {
ctx!.bind(hNode, context);
ctx!.bind(hNode as unknown as HNode, context);
}

if (init) {
init.call(hNode, props, store, ctx!);
}

if (effects) {
hNode.eff = effects.map(effect => effect.call(hNode, props, store, ctx!)).filter(_Boolean) as HCallback<P, S, C, void>[];
}

};
45 changes: 26 additions & 19 deletions src/ext/Portal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,39 @@ export interface PortalStore {

export const Portal = define<PortalProps, Store<PortalStore>, EmptyStore>('HUI.Portal', {

init: function port_init(props, store) {
store.set('p', props.parent || _document.body);
store.set('f', HUI(Fragment, _null, props.children));
},
effects: [
function ptl_eff(props, store) {

render: function port_render(props, store, context) {
renderToDOM(store.get('f'), {
parent: store.get('p'),
owner: this,
context
});
},
const { parent = _document.body } = props,
fragment = HUI(Fragment, _null, props.children);

clear: function port_clear(props, store) {
store.set('p', parent);
store.set('f', fragment);

const fragment = store.get('f')!,
{ ownNode, nodes } = fragment;
return function ptl_clr() {

clear(fragment);
const { ownNode, nodes } = fragment;

nodes!.forEach(node => {
ownNode!.removeChild(node);
});
clear(fragment);

nodes!.forEach(node => {
ownNode!.removeChild(node);
});

nodes!.length = 0;

nodes!.length = 0;
};

}
],


render: function ptl_render(props, store, context) {
renderToDOM(store.get('f'), {
parent: store.get('p'),
owner: this,
context
});
}

});
Expand Down
20 changes: 15 additions & 5 deletions src/utils/clear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,22 @@ export const clear = function clr(hNode: HNode<any>) {

if (desc) {

if (desc.clear) {
try {
desc.clear.call(hNode, props, hNode.sto!, hNode.ctx!);
} catch (err) {
_console.error(err);
const { sto, ctx } = hNode;

try {

if (hNode.eff) {
hNode.eff.forEach(effCanceller => {
effCanceller.call(hNode, props, sto!, ctx!);
});
}

if (desc.clear) {
desc.clear.call(hNode, props, sto!, ctx!);
}

} catch (err) {
_console.error(err);
}

} else {
Expand Down
16 changes: 9 additions & 7 deletions test/src/Timer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ interface TimerProps {

interface TimerStore {
time: number;
timer: any;
}

type TimerStoreHandlers = {
Expand All @@ -19,17 +18,24 @@ const Timer = HUI.define<TimerProps, HUI.Store<TimerStore, TimerStoreHandlers>,
start: 0
},

effects: [
function (props, store) {
const timer = store.trigger('setInterval', 1000);
return () => {
clearInterval(timer);
};
}
],

storeHandlers: {
setInterval(interval) {
const timer = setInterval(this.inc, interval, 'time');
this.set('timer', timer);
return timer;
}
},

init(props, store) {
store.set('time', props.start!);
store.set('timer', store.trigger('setInterval', 1000));
},

render(props, store) {
Expand All @@ -38,10 +44,6 @@ const Timer = HUI.define<TimerProps, HUI.Store<TimerStore, TimerStoreHandlers>,
Time: <span>{store.get('time')}</span>
</HUI.Fragment>
);
},

clear(props, store) {
clearInterval(store.get('timer'));
}

});

0 comments on commit c565bcd

Please sign in to comment.