add onceGot

This commit is contained in:
kangwei 2020-04-16 14:24:03 +08:00
parent 0e877e64d5
commit 5dc04152d5
6 changed files with 200 additions and 20 deletions

View File

@ -31,6 +31,15 @@ export interface GetOptions {
forceNew?: boolean; forceNew?: boolean;
sourceCls?: ClassType; sourceCls?: ClassType;
} }
export type GetReturnType<T, ClsType> = T extends undefined
? ClsType extends {
prototype: infer R;
}
? R
: any
: T;
const NOT_FOUND = Symbol.for('not_found');
export default class Editor extends EventEmitter { export default class Editor extends EventEmitter {
static getInstance = (config: EditorConfig, components: PluginClassSet, utils?: Utils): Editor => { static getInstance = (config: EditorConfig, components: PluginClassSet, utils?: Utils): Editor => {
@ -55,7 +64,9 @@ export default class Editor extends EventEmitter {
/** /**
* Ioc Container * Ioc Container
*/ */
readonly context = new IocContext(); private context = new IocContext({
notFoundHandler: (type: KeyType) => NOT_FOUND,
});
pluginStatus?: PluginStatusSet; pluginStatus?: PluginStatusSet;
@ -86,8 +97,7 @@ export default class Editor extends EventEmitter {
registShortCuts(shortCuts, this); registShortCuts(shortCuts, this);
this.emit('editor.afterInit'); this.emit('editor.afterInit');
return true; return true;
} } catch (err) {
catch (err) {
console.error(err); console.error(err);
} }
} }
@ -105,8 +115,12 @@ export default class Editor extends EventEmitter {
} }
} }
get<T = undefined, KeyOrType = any>(keyOrType: KeyOrType, opt?: GetOptions) { get<T = undefined, KeyOrType = any>(keyOrType: KeyOrType, opt?: GetOptions): GetReturnType<T, KeyOrType> | undefined {
return this.context.get<T, KeyOrType>(keyOrType, opt); const x = this.context.get<T, KeyOrType>(keyOrType, opt);
if (x === NOT_FOUND) {
return undefined;
}
return x;
} }
has(keyOrType: KeyType): boolean { has(keyOrType: KeyType): boolean {
@ -114,11 +128,79 @@ export default class Editor extends EventEmitter {
} }
set(key: KeyType, data: any): void { set(key: KeyType, data: any): void {
this.context.register(data, key); if (this.context.has(key)) {
this.context.replace(key, data, undefined, true);
} else {
this.context.register(data, key);
}
this.notifyGot(key);
}
private waits = new Map<
KeyType,
Array<{
once?: boolean;
resolve: (data: any) => void;
}>
>();
private notifyGot(key: KeyType) {
let waits = this.waits.get(key);
if (!waits) {
return;
}
waits = waits.slice().reverse();
let i = waits.length;
while (i--) {
waits[i].resolve(this.get(key));
if (waits[i].once) {
waits.splice(i, 1);
}
}
if (waits.length > 0) {
this.waits.set(key, waits);
} else {
this.waits.delete(key);
}
}
private setWait(key: KeyType, resolve: (data: any) => void, once?: boolean) {
const waits = this.waits.get(key);
if (waits) {
waits.push({ resolve, once });
} else {
this.waits.set(key, [{ resolve, once }]);
}
}
onceGot<T = undefined, KeyOrType extends KeyType = any>(keyOrType: KeyOrType): Promise<GetReturnType<T, KeyOrType>> {
const x = this.context.get<T, KeyOrType>(keyOrType);
if (x !== NOT_FOUND) {
return Promise.resolve(x);
}
return new Promise((resolve) => {
this.setWait(keyOrType, resolve, true);
});
}
onGot<T = undefined, KeyOrType extends KeyType = any>(
keyOrType: KeyOrType,
fn: (data: GetReturnType<T, KeyOrType>) => void,
): () => void {
const x = this.context.get<T, KeyOrType>(keyOrType);
if (x !== NOT_FOUND) {
fn(x);
return () => {};
} else {
this.setWait(keyOrType, fn);
return () => {
};
}
} }
register(data: any, key?: KeyType, options?: RegisterOptions): void { register(data: any, key?: KeyType, options?: RegisterOptions): void {
this.context.register(data, key, options); this.context.register(data, key, options);
this.notifyGot(key || data);
} }
batchOn(events: string[], lisenter: (...args: any[]) => void): void { batchOn(events: string[], lisenter: (...args: any[]) => void): void {

View File

@ -144,8 +144,8 @@ export default class Mixin extends PureComponent {
); );
} }
} }
let TargetNode = this.typeMap[this.state.type]['component'] || 'div'; let TargetNode = this.typeMap[this.state.type]?.component || 'div';
let targetProps = this.typeMap[this.state.type]['props'] || {}; let targetProps = this.typeMap[this.state.type]?.props || {};
let tarStyle = { position: 'relative', ...style }; let tarStyle = { position: 'relative', ...style };
let classes = classNames(className, 'lowcode-setter-mixin'); let classes = classNames(className, 'lowcode-setter-mixin');

View File

@ -14,11 +14,11 @@
<link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" /> <link rel="stylesheet" href="https://alifd.alicdn.com/npm/@alifd/next/1.11.6/next.min.css" />
<script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script> <script src="https://unpkg.alibaba-inc.com/@alifd/next@1.18.17/dist/next.min.js"></script>
<!-- lowcode engine globals --> <!-- lowcode engine globals -->
<link rel="stylesheet" href="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.8.0/globals.css" /> <link rel="stylesheet" href="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.9.0/globals.css" />
</head> </head>
<body> <body>
<!-- lowcode engine globals --> <!-- lowcode engine globals -->
<script src="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.8.0/globals.js"></script> <script src="https://dev.g.alicdn.com/ali-lowcode/ali-lowcode-engine/0.9.0/globals.js"></script>
</body> </body>
</html> </html>

View File

@ -1,3 +1,108 @@
/**
*
*/
export type REJECTED = 0 | false;
/**
*
*/
export type LIMITED = 2;
/**
*
*/
export type ALLOWED = true | 4;
export type HandleState = REJECTED | ALLOWED | LIMITED;
/*
* model.editing:(dbclick)
* asCode(gotocode) select - option
* asRichText ()
* asPlainText ()
* null|undefined
* false
* handle-function
*
* ## handle
*
* model.shouldRemoveChild: HandleState | (my, child) => HandleState return false
* model.shouldMoveChild: HandleState | (my, child) => HandleState , return false: ; return 0: 不得改变嵌套关系
* model.shouldRemove: HandleState | (my) => HandleState
* model.shouldMove: HandleState | (my) => HandleState return false, return 0;
*
* ## ()
*
* locate
* model.locate: (my, transferData, mouseEvent?) => Location | null, node
*
* test-RegExp: /^tagName./
* test-Pattern: 'tagName,tagName2,Field-*'
* test-Func: (target, my) => boolean
* Tester: RegExp | Pattern | Func | { exclude: Tester, include: Tester }
*
* model.accept
* accept: '@CHILD' slot TabsLayoutColumnsLayout,
* accept: false|null inputoption
* accept: true ok div,
* accept: Tester, filter条件 select线
* model.nesting (nextTick异步检查)
* null | undefined | false | true |
* Tester
* model.dropTarget
* Tester // 实时约束
* {
* highlight?: Tester | boolean, // 高亮默认false设为true时根据 parent | ancestor 取值
* parent?: Tester, // 实时约束,主视图限制定位,大纲树定位进去时红线提示
* ancestor?: Tester, // 异步检查,上文检查, 设置此值时parent 可不设置
* }
* '@ROOT'
* null | undefined | boolean |
*
*
*
*
* 1. /UL li
* 2. Form Button, Input
* 3. @千緖
* 4. Li ULLi设置的 dropTargetRules
* 5.
*
* &
*/
export interface BehaviorControl {
handleMove?: HandleState | ((my: ElementNode) => HandleState);
handleRemove?: HandleState | ((my: ElementNode) => HandleState);
handleChildMove?: HandleState | ((my: ElementNode, child: INode) => HandleState);
handleChildRemove?: HandleState | ((my: ElementNode, child: INode) => HandleState);
}
export const AT_CHILD = Symbol.for('@CHILD');
export const AT_ROOT = Symbol.for('@ROOT');
export type AT_ROOT = typeof AT_ROOT;
export type AT_CHILD = typeof AT_CHILD;
export type AcceptFunc = (
my: ElementNode,
e: LocateEvent | KeyboardEvent | MouseEvent,
) => LocationData | INodeParent | AT_CHILD | null;
// should appear couple
export interface AcceptControl {
/**
* MouseEvent: drag a entiy from browser out
* KeyboardEvent: paste a entiy
* LocateEvent: drag a entiy from pane
*/
accept?: AcceptFunc | AT_CHILD;
handleAccept?: (my: ElementNode, locationData: LocationData) => void;
}
export interface ContentEditable {
propTarget: string;
selector?: string;
}
export enum DISPLAY_TYPE { export enum DISPLAY_TYPE {
NONE = 'none', NONE = 'none',
PLAIN = 'plain', PLAIN = 'plain',

View File

@ -12,12 +12,10 @@ registerSetters();
export const editor = new Editor(); export const editor = new Editor();
globalContext.register(editor, Editor); globalContext.register(editor, Editor);
export const skeleton = new Skeleton(); export const skeleton = new Skeleton(editor);
editor.set(Skeleton, skeleton);
console.info(skeleton.editor);
export const designer = new Designer({ eventPipe: editor }); export const designer = new Designer({ eventPipe: editor });
editor.set(Designer, designer); editor.set(Designer, designer);
skeleton.mainArea.add({ skeleton.mainArea.add({

View File

@ -1,5 +1,4 @@
import { Editor } from '@ali/lowcode-editor-core'; import { Editor } from '@ali/lowcode-editor-core';
import { inject } from '@ali/lowcode-globals';
import { import {
DockConfig, DockConfig,
PanelConfig, PanelConfig,
@ -29,8 +28,6 @@ export enum SkeletonEvents {
WIDGET_HIDE = 'skeleton.widget.hide', WIDGET_HIDE = 'skeleton.widget.hide',
} }
console.log(inject);
export class Skeleton { export class Skeleton {
private panels = new Map<string, Panel>(); private panels = new Map<string, Panel>();
private containers = new Map<string, WidgetContainer<any>>(); private containers = new Map<string, WidgetContainer<any>>();
@ -44,9 +41,7 @@ export class Skeleton {
readonly bottomArea: Area<PanelConfig, Panel>; readonly bottomArea: Area<PanelConfig, Panel>;
readonly stages: Area<StageConfig, Stage>; readonly stages: Area<StageConfig, Stage>;
@inject() public editor: Editor; constructor(readonly editor: Editor) {
constructor() {
this.leftArea = new Area( this.leftArea = new Area(
this, this,
'leftArea', 'leftArea',