重构了启动部分的代码,老的还没删

This commit is contained in:
Xu Chang 2022-06-29 13:24:07 +08:00
parent c9b9752991
commit fdbf535b4d
5 changed files with 444 additions and 16 deletions

7
src/initialize.dev.ts Normal file
View File

@ -0,0 +1,7 @@
/**
* vs code能正确定位webpack编译时应该跳过initialize.dev.mp.ts获initialize.dev.web.ts
*/
import { initialize as initMp } from './initialize.dev.mp';
console.log('不应该跑到这里');
export const initialize = initMp;

77
src/initialize.dev.web.ts Normal file
View File

@ -0,0 +1,77 @@
import './utils/wx.polyfill';
import { Aspect, AspectWrapper, Checker, Trigger, StorageSchema, Context, RowStore, OakRowInconsistencyException, Watcher } from "oak-domain/lib/types";
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { Feature } from './types/Feature';
import { BasicFeatures } from './features';
import { assign } from 'lodash';
import { ActionDictOfEntityDict } from "oak-domain/lib/types/Action";
import { CommonAspectDict } from "oak-common-aspect";
import { ExceptionHandler, ExceptionRouters } from "./types/ExceptionRoute";
import { OakComponentOption, OakPageOption } from "./types/Page";
import { createComponent, createPage } from "./page.web";
import { initialize as initDev } from './initialize-dev';
export function initialize<ED extends EntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>>(
storageSchema: StorageSchema<ED>,
createFeatures: (aspectWrapper: AspectWrapper<ED, Cxt, AD>, basicFeatures: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>, context: Cxt) => FD,
contextBuilder: (cxtString?: string) => (store: RowStore<ED, Cxt>) => Cxt,
aspectDict: AD,
translations: Record<string, any>,
exceptionRouters: ExceptionRouters = [],
triggers?: Array<Trigger<ED, keyof ED, Cxt>>,
checkers?: Array<Checker<ED, keyof ED, Cxt>>,
watchers?: Array<Watcher<ED, keyof ED, Cxt>>,
initialData?: {
[T in keyof ED]?: Array<ED[T]['OpSchema']>;
},
actionDict?: ActionDictOfEntityDict<ED>
) {
const { features, context } = initDev<ED, Cxt, AD, FD>(
storageSchema,
createFeatures,
contextBuilder,
aspectDict,
triggers,
checkers,
watchers,
initialData,
actionDict
);
const exceptionRouterDict: Record<string, ExceptionHandler> = {};
for (const router of exceptionRouters) {
assign(exceptionRouterDict, {
[router[0].name]: router[1],
});
}
assign(global, {
OakPage: <
T extends keyof ED,
Proj extends ED[T]['Selection']['data'],
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(options: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>) => createPage<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>(
options,
features,
exceptionRouterDict,
context),
OakComponent: <
T extends keyof ED,
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(options: OakComponentOption<ED, T, Cxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod>) => createComponent<ED, T, Cxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod>(
options,
features,
exceptionRouterDict,
context),
});
}

View File

@ -8,15 +8,22 @@ import { Feature, subscribe } from "./types/Feature";
import { NamedFilterItem, NamedSorterItem } from "./types/NamedCondition";
import { OakCommonComponentMethods, OakComponentData, OakComponentOption, OakComponentProperties, OakHiddenComponentMethods, OakListComponentMethods, OakPageMethods, OakPageOption } from "./types/Page";
export type ComponentProps<TProperty extends WechatMiniprogram.Component.PropertyOption> = WechatMiniprogram.Component.PropertyOptionToData<OakComponentProperties & TProperty>;
export type ComponentData<ED extends EntityDict,
T extends keyof ED,
FormedData extends WechatMiniprogram.Component.DataOption,
TData extends WechatMiniprogram.Component.DataOption> = TData & FormedData & OakComponentData<ED, T>;
export type ComponentThisType<ED extends EntityDict,
T extends keyof ED,
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}> = ThisType<{
state: TData & FormedData & OakComponentData<ED, T>;
props: WechatMiniprogram.Component.PropertyOptionToData<OakComponentProperties & TProperty>;
TData extends WechatMiniprogram.Component.DataOption,
TProperty extends WechatMiniprogram.Component.PropertyOption,
TMethod extends WechatMiniprogram.Component.MethodOption> = ThisType<{
state: ComponentData<ED, T, FormedData, TData>;
props: ComponentProps<TProperty>;
setState: (
data: any,
callback?: () => void,
@ -37,9 +44,9 @@ export function makeHiddenComponentMethods<ED extends EntityDict,
T extends keyof ED,
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}>(): OakHiddenComponentMethods & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
TData extends WechatMiniprogram.Component.DataOption,
TProperty extends WechatMiniprogram.Component.PropertyOption,
TMethod extends WechatMiniprogram.Component.MethodOption>(): OakHiddenComponentMethods & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
return {
subscribe() {
@ -74,12 +81,12 @@ export function makeCommonComponentMethods<ED extends EntityDict,
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
exceptionRouterDict: Record<string, ExceptionHandler>,
formData: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>['formData']
): Omit<OakCommonComponentMethods<ED, T>, 'navigateTo' | 'navigateBack' | 'resolveInput'> & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
): Omit<OakCommonComponentMethods<ED, T>, 'navigateTo' | 'navigateBack' | 'resolveInput'> & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
return {
t(key: string, params?: object) {
return 'not implemented';
},
async reRender(extra) {
if (this.state.oakFullpath) {
const rows = features.runningTree.getFreshValue(this.state.oakFullpath);
@ -149,7 +156,7 @@ export function makeCommonComponentMethods<ED extends EntityDict,
url,
});
},
setForeignKey(id: string, goBackDelta: number = -1) {
if (this.state.oakExecuting) {
return;
@ -305,9 +312,7 @@ export function makeCommonComponentMethods<ED extends EntityDict,
};
}
export
function makeListComponentMethods<ED extends EntityDict,
export function makeListComponentMethods<ED extends EntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
@ -531,7 +536,7 @@ export function makePageMethods<ED extends EntityDict,
}) : sorter,
['#name']: name,
});
}
}
}
const path2 = oakParent ? `${oakParent}:${oakPath || options.path}` : oakPath || options.path;
const node = await features.runningTree.createNode({

339
src/page.web.tsx Normal file
View File

@ -0,0 +1,339 @@
import React, { Component, PureComponent } from 'react';
import PullToRefresh from './platforms/web/PullToRefresh';
import Wrapper from './platforms/web/Wrapper';
import { assign, omit } from "lodash";
import { CommonAspectDict } from "oak-common-aspect";
import { Aspect, Context, EntityDict } from "oak-domain/lib/types";
import { BasicFeatures } from "./features";
import { ExceptionHandler } from "./types/ExceptionRoute";
import { Feature } from "./types/Feature";
import { OakCommonComponentMethods, OakComponentOption, OakPageData, OakPageMethods, OakPageOption, OakPageProperties } from "./types/Page";
import { ComponentThisType, makeHiddenComponentMethods, makeListComponentMethods, makeCommonComponentMethods as makeCommon, makePageMethods as makePage, ComponentData, ComponentProps } from './page.common';
function makeCommonComponentMethods<ED extends EntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
FormedData extends WechatMiniprogram.Component.DataOption,
Proj extends ED[T]['Selection']['data'],
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}>(
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
exceptionRouterDict: Record<string, ExceptionHandler>,
formData: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>['formData']
): OakCommonComponentMethods<ED, T> & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
return {
resolveInput: (input: WechatMiniprogram.CustomEvent, keys) => {
const { currentTarget, detail } = input;
const { dataset } = currentTarget;
const { value } = detail;
const result = {
dataset,
value,
};
if (keys) {
keys.forEach(
(k) => assign(result, {
[k]: detail[k]
})
)
}
return result;
},
navigateBack: (option) => wx.navigateBack(option),
navigateTo(options) {
const { url, events, fail, complete, success, ...rest } = options;
let url2 = url.includes('?') ? url.concat(`&oakFrom=${this.state.oakFullpath}`) : url.concat(`?oakFrom=${this.state.oakFullpath}`);
for (const param in rest) {
const param2 = param as unknown as keyof typeof rest;
url2 += `&${param}=${typeof rest[param2] === 'string' ? rest[param2] : JSON.stringify(rest[param2])}`;
}
assign(options, {
url: url2
});
return wx.navigateTo(options);
},
...makeCommon(features, exceptionRouterDict, formData),
};
}
function makePageMethods<ED extends EntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
FormedData extends WechatMiniprogram.Component.DataOption,
Proj extends ED[T]['Selection']['data'],
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}>(
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
options: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>
): OakPageMethods & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
const { onPullDownRefresh, ...rest } = makePage(features, options);
return {
async onPullDownRefresh() {
await onPullDownRefresh.call(this);
if (!this.state.oakLoading) {
await wx.stopPullDownRefresh();
}
},
...rest,
};
}
const DEFAULT_REACH_BOTTOM_DISTANCE = 50;
export function createPage<
ED extends EntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
Proj extends ED[T]['Selection']['data'],
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(
options: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>,
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
exceptionRouterDict: Record<string, ExceptionHandler>,
context: Cxt
) {
const { formData, isList, render } = options as OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod> & {
render: () => React.ReactNode & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod>;
};
const hiddenMethods = makeHiddenComponentMethods();
const commonMethods = makeCommonComponentMethods(features, exceptionRouterDict, formData);
const listMethods = isList ? makeListComponentMethods(features) : {};
const { onLoad, onPullDownRefresh, onReachBottom, ...restPageMethods } = makePageMethods(features, options);
const { methods, lifetimes, pageLifetimes, data } = options;
class OakPageWrapper extends PureComponent<ComponentProps<TProperty>, ComponentData<ED, T, FormedData, TData>> {
constructor(props: any) {
super(props);
this.state = (data || {}) as any;
/* for (const m in hiddenMethods) {
assign(this, {
[m]: hiddenMethods[m as keyof typeof hiddenMethods]!.bind(this),
});
} */
for (const m in commonMethods) {
assign(this, {
[m]: commonMethods[m as keyof typeof commonMethods]!.bind(this),
});
}
for (const m in listMethods) {
assign(this, {
[m]: (listMethods as Record<string, Function>)[m as keyof typeof listMethods]!.bind(this),
});
}
for (const m in restPageMethods) {
assign(this, {
[m]: restPageMethods[m as keyof typeof restPageMethods]!.bind(this),
});
}
if (methods) {
const { onLoad, onPullDownRefresh, onReachBottom, ...restMethods } = methods;
for (const m in restMethods) {
assign(this, {
[m]: restMethods[m as keyof typeof restMethods]!.bind(this),
});
}
}
context.setScene(options.path);
lifetimes?.created && lifetimes.created.call(this);
hiddenMethods.subscribe.call(this);
lifetimes?.attached && lifetimes.attached.call(this);
onLoad.call(this, this.props);
}
features = features;
isReachBottom = false;
scrollEvent = () => {
this.checkReachBottom();
const event = { scrollTop: window.scrollY };
};
registerPageScroll () {
window.addEventListener('scroll', this.scrollEvent);
};
unregisterPageScroll () {
window.removeEventListener('scroll', this.scrollEvent);
};
checkReachBottom () {
const isCurrentReachBottom =
document.body.scrollHeight -
(window.innerHeight + window.scrollY) <= DEFAULT_REACH_BOTTOM_DISTANCE;
if (!this.isReachBottom && isCurrentReachBottom) {
this.isReachBottom = true;
// 执行触底事件
onReachBottom.call(this);
methods?.onReachBottom && methods.onReachBottom.call(this);
return;
}
this.isReachBottom = isCurrentReachBottom;
};
componentDidMount() {
methods?.onReady && methods.onReady.call(this);
lifetimes?.ready && lifetimes.ready.call(this);
}
componentWillUnmount() {
hiddenMethods.unsubscribe.call(this);
methods?.onUnload && methods.onUnload.call(this);
lifetimes?.detached && lifetimes.detached.call(this);
}
render(): React.ReactNode {
pageLifetimes?.show && pageLifetimes.show();
const Render = render.call(this);
const { oakLoading } = this.state;
return React.cloneElement(
<PullToRefresh
onRefresh={() => {
onPullDownRefresh.call(this);
methods?.onPullDownRefresh && methods.onPullDownRefresh.call(this);
}}
refreshing={oakLoading}
distanceToRefresh={DEFAULT_REACH_BOTTOM_DISTANCE}
getScrollContainer={() => {
document.body;
}}
/>,
{},
Render
);
}
};
return () => <Wrapper PageWrapper={OakPageWrapper} />;
}
export function createComponent<
ED extends EntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(
options: OakComponentOption<ED, T, Cxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod>,
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
exceptionRouterDict: Record<string, ExceptionHandler>,
context: Cxt
) {
const { formData, isList, entity, methods, lifetimes, pageLifetimes,
data, properties, actions, observers, render } = options as OakComponentOption<ED, T, Cxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod> & {
render: () => React.ReactNode & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod>;
};;
const hiddenMethods = makeHiddenComponentMethods();
const commonMethods = makeCommonComponentMethods(features, exceptionRouterDict, formData);
const listMethods = isList ? makeListComponentMethods(features) : {};
class OakPageWrapper extends PureComponent<ComponentProps<TProperty>, ComponentData<ED, T, FormedData, TData>> {
constructor(props: any) {
super(props);
this.state = (data || {}) as any;
/* for (const m in hiddenMethods) {
assign(this, {
[m]: hiddenMethods[m as keyof typeof hiddenMethods]!.bind(this),
});
} */
for (const m in commonMethods) {
assign(this, {
[m]: commonMethods[m as keyof typeof commonMethods]!.bind(this),
});
}
for (const m in listMethods) {
assign(this, {
[m]: (listMethods as Record<string, Function>)[m as keyof typeof listMethods]!.bind(this),
});
}
if (methods) {
for (const m in methods) {
assign(this, {
[m]: methods[m as keyof typeof methods]!.bind(this),
});
}
}
lifetimes?.created && lifetimes.created.call(this);
hiddenMethods.subscribe.call(this);
lifetimes?.attached && lifetimes.attached.call(this);
}
features = features;
isReachBottom = false;
componentDidMount() {
lifetimes?.ready && lifetimes.ready.call(this);
}
componentWillUnmount() {
hiddenMethods.unsubscribe.call(this);
lifetimes?.detached && lifetimes.detached.call(this);
}
render(): React.ReactNode {
pageLifetimes?.show && pageLifetimes.show();
const Render = render.call(this);
return Render;
}
};
return () => <Wrapper PageWrapper={OakPageWrapper} />;
}
export type MakeOakPage<
ED extends EntityDict,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>
> = <
T extends keyof ED,
Proj extends ED[T]['Selection']['data'],
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption,
TProperty extends WechatMiniprogram.Component.PropertyOption,
TMethod extends WechatMiniprogram.Component.MethodOption
> (options: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>) => JSX.Element;
export type MakeOakComponent<
ED extends EntityDict,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>
> = <
T extends keyof ED,
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption,
TProperty extends WechatMiniprogram.Component.PropertyOption,
TMethod extends WechatMiniprogram.Component.MethodOption
>(options: OakComponentOption<ED, T, Cxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod>) => JSX.Element;

View File

@ -71,7 +71,7 @@
"miniprogram-api-typings"
],
"include": [
"src/**/*.ts",
"src/**/*.ts", "src/page.web.tsx",
],
"exclude": [
"node_modules",