增加了对options中features的定义及实现

This commit is contained in:
Xu Chang 2023-02-19 12:17:19 +08:00
parent 6b93deba6c
commit 2daed01a18
8 changed files with 192 additions and 134 deletions

View File

@ -1785,10 +1785,10 @@ var VirtualNode = /** @class */ (function (_super) {
if (child instanceof SingleNode || child instanceof ListNode) {
var entity = child.getEntity();
if (child instanceof SingleNode) {
(0, assert_1.assert)(path === entity || path.startsWith("".concat(entity, ":")), "oakPath\u300C".concat(path, "\u300D\u4E0D\u7B26\u5408\u547D\u540D\u89C4\u8303\uFF0C\u8BF7\u4EE5\u300C").concat(entity, "\u300D\u4E3A\u547D\u540D\u8D77\u59CB\u6807\u8BC6"));
(0, assert_1.assert)(path === entity || path.startsWith("".concat(entity, ":")), "oakPath\u300C".concat(path, "\u300D\u4E0D\u7B26\u5408\u547D\u540D\u89C4\u8303\uFF0C\u8BF7\u4EE5\u300C").concat(entity, ":\u300D\u4E3A\u547D\u540D\u8D77\u59CB\u6807\u8BC6"));
}
else {
(0, assert_1.assert)(path === "".concat(entity, "s") || path.startsWith("".concat(entity, "s:")), "oakPath\u300C".concat(path, "\u300D\u4E0D\u7B26\u5408\u547D\u540D\u89C4\u8303\uFF0C\u8BF7\u4EE5\u300C").concat(entity, "s\u300D\u4E3A\u547D\u540D\u8D77\u59CB\u6807\u8BC6"));
(0, assert_1.assert)(path === "".concat(entity, "s") || path.startsWith("".concat(entity, "s:")), "oakPath\u300C".concat(path, "\u300D\u4E0D\u7B26\u5408\u547D\u540D\u89C4\u8303\uFF0C\u8BF7\u4EE5\u300C").concat(entity, "s:\u300D\u4E3A\u547D\u540D\u8D77\u59CB\u6807\u8BC6"));
}
}
};

View File

@ -505,6 +505,9 @@ function createComponent(option, features) {
if (option.entity) {
this.subscribed.push(features.cache.subscribe(function () { return _this.reRender(); }));
}
if (option.features) {
option.features.forEach(function (ele) { return _this.subscribed.push(features[ele].subscribe(function () { return _this.reRender(); })); });
}
attached && attached.call(this);
},
detached: function () {

View File

@ -641,7 +641,11 @@ function createComponent(option, features) {
}
this.reRender();
_a.label = 3;
case 3: return [2 /*return*/];
case 3:
if (option.features) {
option.features.forEach(function (ele) { return _this.subscribed.push(features[ele].subscribe(function () { return _this.reRender(); })); });
}
return [2 /*return*/];
}
});
});

16
lib/types/Page.d.ts vendored
View File

@ -38,10 +38,26 @@ declare type FullPropertyToData<T extends AllFullProperty> = ValueType<T['type']
declare type PropertyOptionToData<P extends PropertyOption> = {
[name in keyof P]: PropertyToData<P[name]>;
};
declare type CascadeEntity<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
aggr?: ED[T]['Aggregation'];
selection?: ED[T]['Selection'];
actions?: [
{
action: ED[T]['Action'];
filters?: Array<{
filter: ED[T]['Selection']['filter'];
'#name'?: string;
}>;
data?: Partial<ED[T]['CreateSingle']['data']>;
}
];
};
interface ComponentOption<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature>, FormedData extends Record<string, any>, IsList extends boolean, TData extends DataOption, TProperty extends PropertyOption> {
entity?: T | ((this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty>) => T);
path?: string;
isList: IsList;
features?: (keyof (FD & BasicFeatures<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>))[];
cascadeEntities?: (this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty>) => Record<keyof ED[T]['Schema'], CascadeEntity<ED, keyof ED>>;
projection?: ED[T]['Selection']['data'] | ((this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty>) => ED[T]['Selection']['data']);
append?: boolean;
pagination?: Pagination;

View File

@ -1777,10 +1777,10 @@ class VirtualNode<
if (child instanceof SingleNode || child instanceof ListNode) {
const entity = child.getEntity() as string;
if (child instanceof SingleNode) {
assert(path === entity || path.startsWith(`${entity}:`), `oakPath「${path}」不符合命名规范,请以「${entity}」为命名起始标识`);
assert(path === entity || path.startsWith(`${entity}:`), `oakPath「${path}」不符合命名规范,请以「${entity}:」为命名起始标识`);
}
else {
assert(path === `${entity}s` || path.startsWith(`${entity}s:`), `oakPath「${path}」不符合命名规范,请以「${entity}s」为命名起始标识`);
assert(path === `${entity}s` || path.startsWith(`${entity}s:`), `oakPath「${path}」不符合命名规范,请以「${entity}s:」为命名起始标识`);
}
}
}

View File

@ -761,6 +761,15 @@ export function createComponent<
features.cache.subscribe(() => this.reRender())
);
}
if (option.features) {
option.features.forEach(
ele => this.subscribed.push(
features[ele].subscribe(
() => this.reRender()
)
)
);
}
attached && attached.call(this);
},
detached() {

View File

@ -906,6 +906,15 @@ export function createComponent<
}
this.reRender();
}
if (option.features) {
option.features.forEach(
ele => this.subscribed.push(
features[ele].subscribe(
() => this.reRender()
)
)
);
}
}
componentWillUnmount() {

View File

@ -41,7 +41,7 @@ type ValueType<T extends PropertyType> = T extends null
? AnyObject
: T extends FunctionConstructor
? Function
:never
: never
type FullProperty<T extends PropertyType> = {
/** 属性类型 */
type: T
@ -82,6 +82,21 @@ type PropertyOptionToData<P extends PropertyOption> = {
[name in keyof P]: PropertyToData<P[name]>
};
type CascadeEntity<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED> = {
aggr?: ED[T]['Aggregation'],
selection?: ED[T]['Selection'],
actions?: [{
action: ED[T]['Action'],
filters?: Array<{
filter: ED[T]['Selection']['filter'];
'#name'?: string;
}>;
data?: Partial<ED[T]['CreateSingle']['data']>;
}];
};
interface ComponentOption<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
@ -93,10 +108,12 @@ interface ComponentOption<
IsList extends boolean,
TData extends DataOption,
TProperty extends PropertyOption,
> {
> {
entity?: T | ((this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty>) => T);
path?: string;
isList: IsList;
features?: (keyof (FD & BasicFeatures<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>))[];
cascadeEntities?: (this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty>) => Record<keyof ED[T]['Schema'], CascadeEntity<ED, keyof ED>>,
projection?: ED[T]['Selection']['data'] | ((this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty>) => ED[T]['Selection']['data']);
append?: boolean;
pagination?: Pagination;
@ -147,7 +164,7 @@ export type ComponentData<
T extends keyof ED,
FormedData extends DataOption,
TData extends DataOption
> = TData & FormedData & OakComponentData<ED, T>;
> = TData & FormedData & OakComponentData<ED, T>;
export type ComponentPublicThisType<
ED extends EntityDict & BaseEntityDict,
@ -162,21 +179,21 @@ export type ComponentPublicThisType<
TProperty extends PropertyOption = {},
TMethod extends MethodOption = {},
EMethod extends Record<string, Function> = {}
> = {
subscribed: Array<() => void>;
features: FD & BasicFeatures<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>;
state: ComponentData<ED, T, FormedData, TData>;
props: Readonly<ComponentProps<IsList, TProperty>>;
setState: (
data: Partial<ComponentData<ED, T, FormedData, TData>>,
callback?: () => void,
) => void;
triggerEvent: <DetailType = any>(
name: string,
detail?: DetailType,
options?: WechatMiniprogram.Component.TriggerEventOption
) => void;
} & TMethod & EMethod & OakCommonComponentMethods<ED, T> & OakListComponentMethods<ED, T> & OakSingleComponentMethods<ED, T>;
> = {
subscribed: Array<() => void>;
features: FD & BasicFeatures<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>>;
state: ComponentData<ED, T, FormedData, TData>;
props: Readonly<ComponentProps<IsList, TProperty>>;
setState: (
data: Partial<ComponentData<ED, T, FormedData, TData>>,
callback?: () => void,
) => void;
triggerEvent: <DetailType = any>(
name: string,
detail?: DetailType,
options?: WechatMiniprogram.Component.TriggerEventOption
) => void;
} & TMethod & EMethod & OakCommonComponentMethods<ED, T> & OakListComponentMethods<ED, T> & OakSingleComponentMethods<ED, T>;
export type ComponentFullThisType<
ED extends EntityDict & BaseEntityDict,
@ -184,21 +201,21 @@ export type ComponentFullThisType<
IsList extends boolean,
Cxt extends AsyncContext<ED>,
FrontCxt extends SyncContext<ED>
> = {
subscribed: Array<() => void>;
features: BasicFeatures<ED, Cxt, FrontCxt, CommonAspectDict<ED, Cxt>>;
state: OakComponentData<ED, T>;
props: ComponentProps<true, {}>;
setState: (
data: Partial<OakComponentData<ED, T>>,
callback?: () => void,
) => void;
triggerEvent: <DetailType = any>(
name: string,
detail?: DetailType,
options?: WechatMiniprogram.Component.TriggerEventOption
) => void;
} & OakCommonComponentMethods<ED, T> & OakListComponentMethods<ED, T> & OakSingleComponentMethods<ED, T>;
> = {
subscribed: Array<() => void>;
features: BasicFeatures<ED, Cxt, FrontCxt, CommonAspectDict<ED, Cxt>>;
state: OakComponentData<ED, T>;
props: ComponentProps<true, {}>;
setState: (
data: Partial<OakComponentData<ED, T>>,
callback?: () => void,
) => void;
triggerEvent: <DetailType = any>(
name: string,
detail?: DetailType,
options?: WechatMiniprogram.Component.TriggerEventOption
) => void;
} & OakCommonComponentMethods<ED, T> & OakListComponentMethods<ED, T> & OakSingleComponentMethods<ED, T>;
export type OakComponentOption<
ED extends EntityDict & BaseEntityDict,
@ -213,7 +230,7 @@ export type OakComponentOption<
TProperty extends PropertyOption,
TMethod extends Record<string, Function>,
EMethod extends Record<string, Function> = {}
> = ComponentOption<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty> &
> = ComponentOption<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty> &
Partial<{
methods: TMethod;
lifetimes: {
@ -273,60 +290,60 @@ export type OakNavigateToParameters<ED extends EntityDict & BaseEntityDict, T ex
export type OakCommonComponentMethods<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED
> = {
setDisablePulldownRefresh: (able: boolean) => void;
sub: (type: string, callback: Function) => void;
unsub: (type: string, callback: Function) => void;
pub: (type: string, options?: any) => void;
unsubAll: (type: string) => void;
save: (key: string, item: any) => void;
load: (key: string) => any;
clear: () => void;
resolveInput: <K extends string>(
input: any,
keys?: K[]
) => { dataset?: Record<string, any>; value?: string } & {
[k in K]?: any;
};
setNotification: (data: NotificationProps) => void;
consumeNotification: () => NotificationProps | undefined;
setMessage: (data: MessageProps) => void;
consumeMessage: () => MessageProps | undefined;
reRender: (extra?: Record<string, any>) => void;
getFreshValue: (path?: string) =>
| Partial<ED[keyof ED]['Schema']>[]
| Partial<ED[keyof ED]['Schema']>
| undefined;
navigateTo: <T2 extends keyof ED>(
options: { url: string } & OakNavigateToParameters<ED, T2>,
state?: Record<string, any>,
disableNamespace?: boolean
) => Promise<void>;
navigateBack: (delta?: number) => Promise<void>;
redirectTo: <T2 extends keyof ED>(
options: Parameters<typeof wx.redirectTo>[0] &
OakNavigateToParameters<ED, T2>,
state?: Record<string, any>,
disableNamespace?: boolean
) => Promise<void>;
// setProps: (props: Record<string, any>, usingState?: true) => void;
clean: (path?: string) => void;
t(key: string, params?: object): string;
execute: (action?: ED[T]['Action'], messageProps?: boolean | MessageProps) => Promise<void>;
checkOperation: (
ntity: T,
action: ED[T]['Action'],
filter?: ED[T]['Update']['filter'],
checkerTypes?: CheckerType[]
) => boolean;
tryExecute: (path?: string) => boolean | Error;
getOperations: (
path?: string
) => { operation: ED[T]['Operation']; entity: T }[] | undefined;
refresh: () => Promise<void>;
aggregate: (aggregation: ED[T]['Aggregation']) => Promise<AggregationResult<ED[T]['Schema']>>;
> = {
setDisablePulldownRefresh: (able: boolean) => void;
sub: (type: string, callback: Function) => void;
unsub: (type: string, callback: Function) => void;
pub: (type: string, options?: any) => void;
unsubAll: (type: string) => void;
save: (key: string, item: any) => void;
load: (key: string) => any;
clear: () => void;
resolveInput: <K extends string>(
input: any,
keys?: K[]
) => { dataset?: Record<string, any>; value?: string } & {
[k in K]?: any;
};
setNotification: (data: NotificationProps) => void;
consumeNotification: () => NotificationProps | undefined;
setMessage: (data: MessageProps) => void;
consumeMessage: () => MessageProps | undefined;
reRender: (extra?: Record<string, any>) => void;
getFreshValue: (path?: string) =>
| Partial<ED[keyof ED]['Schema']>[]
| Partial<ED[keyof ED]['Schema']>
| undefined;
navigateTo: <T2 extends keyof ED>(
options: { url: string } & OakNavigateToParameters<ED, T2>,
state?: Record<string, any>,
disableNamespace?: boolean
) => Promise<void>;
navigateBack: (delta?: number) => Promise<void>;
redirectTo: <T2 extends keyof ED>(
options: Parameters<typeof wx.redirectTo>[0] &
OakNavigateToParameters<ED, T2>,
state?: Record<string, any>,
disableNamespace?: boolean
) => Promise<void>;
// setProps: (props: Record<string, any>, usingState?: true) => void;
clean: (path?: string) => void;
t(key: string, params?: object): string;
execute: (action?: ED[T]['Action'], messageProps?: boolean | MessageProps) => Promise<void>;
checkOperation: (
ntity: T,
action: ED[T]['Action'],
filter?: ED[T]['Update']['filter'],
checkerTypes?: CheckerType[]
) => boolean;
tryExecute: (path?: string) => boolean | Error;
getOperations: (
path?: string
) => { operation: ED[T]['Operation']; entity: T }[] | undefined;
refresh: () => Promise<void>;
aggregate: (aggregation: ED[T]['Aggregation']) => Promise<AggregationResult<ED[T]['Schema']>>;
};
export type OakSingleComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
setId: (id: string) => void;
@ -377,31 +394,31 @@ export type OakComponentOnlyMethods = {
export type OakComponentData<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED
> = {
oakExecutable: boolean | Error;
oakExecuting: boolean;
oakFocused: {
attr: string;
message: string;
};
oakDirty: boolean;
oakLoading: boolean;
oakLoadingMore: boolean;
oakPullDownRefreshLoading: boolean;
oakEntity: T;
oakFullpath: string;
oakLegalActions?: ED[T]['Action'][];
oakDisablePulldownRefresh: boolean;
> = {
oakExecutable: boolean | Error;
oakExecuting: boolean;
oakFocused: {
attr: string;
message: string;
};
oakDirty: boolean;
oakLoading: boolean;
oakLoadingMore: boolean;
oakPullDownRefreshLoading: boolean;
oakEntity: T;
oakFullpath: string;
oakLegalActions?: ED[T]['Action'][];
oakDisablePulldownRefresh: boolean;
};
export type OakListComoponetData<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED
> = {
oakFilters?: NonNullable<ED[T]['Selection']['filter']>[];
oakSorters?: NonNullable<ED[T]['Selection']['sorter']>[];
oakPagination?: Pagination;
}
> = {
oakFilters?: NonNullable<ED[T]['Selection']['filter']>[];
oakSorters?: NonNullable<ED[T]['Selection']['sorter']>[];
oakPagination?: Pagination;
}
export type MakeOakComponent<
ED extends EntityDict & BaseEntityDict,
@ -409,28 +426,28 @@ export type MakeOakComponent<
FrontCxt extends SyncContext<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature>
> = <
T extends keyof ED,
FormedData extends DataOption,
IsList extends boolean,
TData extends DataOption,
TProperty extends PropertyOption,
TMethod extends MethodOption
>(
options: OakComponentOption<
ED,
T,
Cxt,
FrontCxt,
AD,
FD,
FormedData,
IsList,
TData,
TProperty,
TMethod
>
) => React.ComponentType<any>;
> = <
T extends keyof ED,
FormedData extends DataOption,
IsList extends boolean,
TData extends DataOption,
TProperty extends PropertyOption,
TMethod extends MethodOption
>(
options: OakComponentOption<
ED,
T,
Cxt,
FrontCxt,
AD,
FD,
FormedData,
IsList,
TData,
TProperty,
TMethod
>
) => React.ComponentType<any>;
// 暴露给组件的方法
export type WebComponentCommonMethodNames = 'setNotification' | 'setMessage' | 'navigateTo' | 'navigateBack' | 'redirectTo' | 'clean' | 't' | 'execute' | 'refresh' | 'setDisablePulldownRefresh' | 'aggregate' | 'checkOperation';