@oinone/kunlun-vue-widget 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/oinone-kunlun-vue-widget.esm.js +16 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/src/basic/AsyncVueWidget.d.ts +7 -0
- package/dist/types/src/basic/VueFragment.vue.d.ts +2 -0
- package/dist/types/src/basic/VueWidget.d.ts +331 -0
- package/dist/types/src/basic/Widget.d.ts +234 -0
- package/dist/types/src/basic/index.d.ts +3 -0
- package/dist/types/src/data/ActiveRecordsWidget.d.ts +246 -0
- package/dist/types/src/data/PathWidget.d.ts +34 -0
- package/dist/types/src/data/index.d.ts +2 -0
- package/dist/types/src/dsl/DslDefinitionWidget.d.ts +61 -0
- package/dist/types/src/dsl/DslNodeWidget.d.ts +42 -0
- package/dist/types/src/dsl/DslRenderWidget.d.ts +44 -0
- package/dist/types/src/dsl/index.d.ts +3 -0
- package/dist/types/src/feature/index.d.ts +1 -0
- package/dist/types/src/feature/invisible-supported.d.ts +11 -0
- package/dist/types/src/hooks/all-mounted.d.ts +20 -0
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/index.d.ts +9 -0
- package/dist/types/src/token/index.d.ts +2 -0
- package/dist/types/src/typing/WidgetTagContext.d.ts +39 -0
- package/dist/types/src/typing/WidgetTagProps.d.ts +23 -0
- package/dist/types/src/typing/index.d.ts +3 -0
- package/dist/types/src/typing/typing.d.ts +7 -0
- package/dist/types/src/util/dsl-render.d.ts +106 -0
- package/dist/types/src/util/index.d.ts +4 -0
- package/dist/types/src/util/install.d.ts +4 -0
- package/dist/types/src/util/render.d.ts +7 -0
- package/dist/types/src/util/widget-manager.d.ts +4 -0
- package/dist/types/src/view/index.d.ts +161 -0
- package/index.ts +1 -0
- package/package.json +34 -0
- package/rollup.config.js +21 -0
- package/src/basic/AsyncVueWidget.ts +31 -0
- package/src/basic/VueFragment.vue +11 -0
- package/src/basic/VueWidget.ts +997 -0
- package/src/basic/Widget.ts +675 -0
- package/src/basic/index.ts +3 -0
- package/src/data/ActiveRecordsWidget.ts +572 -0
- package/src/data/PathWidget.ts +82 -0
- package/src/data/index.ts +2 -0
- package/src/dsl/DslDefinitionWidget.ts +235 -0
- package/src/dsl/DslNodeWidget.ts +130 -0
- package/src/dsl/DslRenderWidget.ts +106 -0
- package/src/dsl/index.ts +3 -0
- package/src/feature/index.ts +1 -0
- package/src/feature/invisible-supported.ts +29 -0
- package/src/hooks/all-mounted.ts +179 -0
- package/src/hooks/index.ts +1 -0
- package/src/index.ts +9 -0
- package/src/shim-translate.d.ts +7 -0
- package/src/shim-vue.d.ts +6 -0
- package/src/token/index.ts +8 -0
- package/src/typing/WidgetTagContext.ts +53 -0
- package/src/typing/WidgetTagProps.ts +24 -0
- package/src/typing/index.ts +3 -0
- package/src/typing/typing.ts +7 -0
- package/src/util/dsl-render.ts +464 -0
- package/src/util/index.ts +4 -0
- package/src/util/install.ts +29 -0
- package/src/util/render.ts +21 -0
- package/src/util/widget-manager.ts +14 -0
- package/src/view/index.ts +416 -0
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
import { IWidget, WidgetConstructor, WidgetProps } from '@oinone/kunlun-engine';
|
|
2
|
+
import { instantiate } from '@oinone/kunlun-shared';
|
|
3
|
+
import { BehaviorSubject, Subject, Subscription } from '@oinone/kunlun-state';
|
|
4
|
+
import { InnerWidgetType } from '../typing/typing';
|
|
5
|
+
|
|
6
|
+
interface NameContextMap<T> {
|
|
7
|
+
paramName_NameMap: Map<string, Symbol>;
|
|
8
|
+
subject: BehaviorSubject<T> | Subject<T>;
|
|
9
|
+
value?: T;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface BaseWidgetSubjection<T> {
|
|
13
|
+
subscribe: (func: (data: T) => void) => Subscription;
|
|
14
|
+
subject: BehaviorSubject<T> | Subject<T>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface WidgetSubjection<T> extends BaseWidgetSubjection<T> {
|
|
18
|
+
subject: Subject<T>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface WidgetBehaviorSubjection<T> extends BaseWidgetSubjection<T> {
|
|
22
|
+
subject: BehaviorSubject<T>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type watcher<T> = { path: string; handler: (newVal: T, oldVal: T) => void; options?: { deep?: boolean } };
|
|
26
|
+
export type HANDLE = string;
|
|
27
|
+
|
|
28
|
+
export abstract class Widget<Props extends WidgetProps = WidgetProps, R = unknown> implements IWidget<Props> {
|
|
29
|
+
private static widgetCount = 0;
|
|
30
|
+
|
|
31
|
+
private static createHandle(name = ''): HANDLE {
|
|
32
|
+
return `${name || 'oio-widget'}-${this.widgetCount++}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private static widgetMap: Map<string, Widget> = new Map();
|
|
36
|
+
|
|
37
|
+
private static attributeMap: Map<Function, Map<string, string>> = new Map();
|
|
38
|
+
|
|
39
|
+
private static protoChainsCache = new WeakMap<Function, Function[]>();
|
|
40
|
+
|
|
41
|
+
private static watchMap: Map<Function, watcher<unknown>[]> = new Map();
|
|
42
|
+
|
|
43
|
+
private static nameContextMap: Map<Symbol, NameContextMap<unknown>> = new Map();
|
|
44
|
+
|
|
45
|
+
private subscriptionMap = new Map<Symbol, Subscription>();
|
|
46
|
+
|
|
47
|
+
private $$props?: string[];
|
|
48
|
+
|
|
49
|
+
private static Attribute(params?: { displayName?: string; render?: boolean }) {
|
|
50
|
+
return <T extends Widget, K>(target: T, nativeName: string, description?: TypedPropertyDescriptor<K>) => {
|
|
51
|
+
const widgetType = target.constructor;
|
|
52
|
+
const attrs = this.attributeMap.get(widgetType) || new Map();
|
|
53
|
+
attrs.set((params && params.displayName) || nativeName, nativeName);
|
|
54
|
+
this.attributeMap.set(widgetType, attrs);
|
|
55
|
+
if (description && description.get) {
|
|
56
|
+
target[`$compute$${nativeName}`] = { get: description.get, set: description.set };
|
|
57
|
+
}
|
|
58
|
+
const $$props = widgetType.prototype.$$props || [];
|
|
59
|
+
if (!params || params.render !== false) {
|
|
60
|
+
$$props.push((params && params.displayName) || nativeName);
|
|
61
|
+
}
|
|
62
|
+
target.$$props = $$props;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 添加事件监听
|
|
68
|
+
*
|
|
69
|
+
* @param {string} path 监听的路径
|
|
70
|
+
* @param {deep?:boolean;immediate?:boolean} options?
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
*
|
|
74
|
+
* @Widget.Watch('formData.name', {deep: true, immediate: true})
|
|
75
|
+
* private watchName(name: string) {
|
|
76
|
+
* ... todo
|
|
77
|
+
* }
|
|
78
|
+
*
|
|
79
|
+
*/
|
|
80
|
+
protected static Watch(path: string, options?: { deep?: boolean; immediate?: boolean }) {
|
|
81
|
+
return <T extends Widget, K>(
|
|
82
|
+
target: T,
|
|
83
|
+
nativeName: string,
|
|
84
|
+
descriptor:
|
|
85
|
+
| TypedPropertyDescriptor<(newValue: K, oldValue?: K) => void>
|
|
86
|
+
| TypedPropertyDescriptor<(newValue: K, oldValue?: K) => Promise<void>>
|
|
87
|
+
| TypedPropertyDescriptor<(newValue?: K, oldValue?: K) => void>
|
|
88
|
+
| TypedPropertyDescriptor<(newValue?: K, oldValue?: K) => Promise<void>>
|
|
89
|
+
) => {
|
|
90
|
+
const name = target.constructor;
|
|
91
|
+
const watchMap = Widget.watchMap.get(name) || [];
|
|
92
|
+
watchMap.push({
|
|
93
|
+
path,
|
|
94
|
+
handler: descriptor.value! as (newVal: unknown, oldVal?: unknown) => void,
|
|
95
|
+
options
|
|
96
|
+
});
|
|
97
|
+
Widget.watchMap.set(name, watchMap);
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private static Sub<T>(name: Symbol, SubjectType: { new (T): Subject<T> | BehaviorSubject<T> }, value?: T) {
|
|
102
|
+
return <K extends Widget>(target: K, paramName: string) => {
|
|
103
|
+
const nameContextMap = this.nameContextMap.get(name);
|
|
104
|
+
if (!nameContextMap) {
|
|
105
|
+
const subject = new SubjectType(value);
|
|
106
|
+
const paramName_NameMap = new Map<string, Symbol>();
|
|
107
|
+
paramName_NameMap.set(paramName, name);
|
|
108
|
+
this.nameContextMap.set(name, {
|
|
109
|
+
paramName_NameMap,
|
|
110
|
+
subject,
|
|
111
|
+
value
|
|
112
|
+
} as NameContextMap<unknown>);
|
|
113
|
+
} else if (nameContextMap && !nameContextMap.paramName_NameMap.get(paramName)) {
|
|
114
|
+
nameContextMap.paramName_NameMap.set(paramName, name);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 可以用来处理不同widget之间的通讯,当被订阅的时候,会将默认值发送出去
|
|
121
|
+
*
|
|
122
|
+
* @param {Symbol} name 唯一标示
|
|
123
|
+
* @param {unknown} value? 默认值
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
*
|
|
127
|
+
* const identifier = Symbol('example-sub')
|
|
128
|
+
*
|
|
129
|
+
* * field.ts * // 文件
|
|
130
|
+
*
|
|
131
|
+
* @Widget.BehaviorSubContext(identifier, {value: '这是默认值'})
|
|
132
|
+
* private exampleSub!:WidgetBehaviorSubjection<{value: string}>
|
|
133
|
+
*
|
|
134
|
+
* onValueChange() {
|
|
135
|
+
* this.exampleSub.subject.next({value: '这是新的值'})
|
|
136
|
+
* }
|
|
137
|
+
*
|
|
138
|
+
* * other-field.ts * // 文件
|
|
139
|
+
* @Widget.BehaviorSubContext(identifier, {value: '这是默认值'})
|
|
140
|
+
* private exampleSub!:WidgetBehaviorSubjection<{value: string}>
|
|
141
|
+
*
|
|
142
|
+
* mounted() {
|
|
143
|
+
* this.exampleSub.subscribe((value) => {
|
|
144
|
+
* ...todo
|
|
145
|
+
* })
|
|
146
|
+
* }
|
|
147
|
+
*
|
|
148
|
+
*/
|
|
149
|
+
protected static BehaviorSubContext(name: Symbol, value?: unknown) {
|
|
150
|
+
return Widget.Sub(name, BehaviorSubject, value);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 与 `BehaviorSubContext` 一样,区别在于第一次不会发射默认值
|
|
155
|
+
*
|
|
156
|
+
* @param {Symbol} name 唯一标示
|
|
157
|
+
* @param {unknown} value? 默认值
|
|
158
|
+
*/
|
|
159
|
+
protected static SubContext(name: Symbol, value?: unknown) {
|
|
160
|
+
return Widget.Sub(name, Subject, value);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* 将数据绑定为响应式,并且组件中可以获取该值
|
|
165
|
+
*/
|
|
166
|
+
protected static Reactive(params?: { displayName?: string; render?: boolean }) {
|
|
167
|
+
return Widget.Attribute(params);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 将方法绑定为能够被组件获取的方法
|
|
172
|
+
*/
|
|
173
|
+
protected static Method(displayName?: string) {
|
|
174
|
+
return Widget.Attribute(displayName ? { displayName } : undefined);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public static select<T extends Widget = Widget>(handle: string): T | undefined {
|
|
178
|
+
return Widget.widgetMap.get(handle) as T | undefined;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* 获取上级注入的依赖,与 Provide 一起使用
|
|
183
|
+
*
|
|
184
|
+
* @param {string|Symbol} injectName? 被注入的name,如果不传递,那么取target中的name
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
*
|
|
188
|
+
* * children.ts * // 文件
|
|
189
|
+
*
|
|
190
|
+
* @Widget.Inject('InjectName')
|
|
191
|
+
* private rootData!:
|
|
192
|
+
*
|
|
193
|
+
* 如果要将该值变为响应式,如果加上Reactive
|
|
194
|
+
*
|
|
195
|
+
* @Widget.Reactive()
|
|
196
|
+
* @Widget.Inject('InjectName')
|
|
197
|
+
* private rootData!:;
|
|
198
|
+
*/
|
|
199
|
+
protected static Inject(injectName?: string | Symbol) {
|
|
200
|
+
return <T extends Widget>(target: T, name: string) => {
|
|
201
|
+
let injection: { name: typeof Widget; list: Map<string | Symbol, string> } = Reflect.get(target, 'injection') || {
|
|
202
|
+
name: this,
|
|
203
|
+
list: new Map()
|
|
204
|
+
};
|
|
205
|
+
if (injection.name !== target.constructor) {
|
|
206
|
+
const oldInjection = injection;
|
|
207
|
+
injection = { name: target.constructor as typeof Widget, list: new Map() };
|
|
208
|
+
oldInjection.list.forEach((v, n) => injection.list.set(n, v));
|
|
209
|
+
Reflect.set(target, 'injection', injection);
|
|
210
|
+
}
|
|
211
|
+
// const injection = Reflect.get(target, 'injection') as Map<string | Symbol, string>;
|
|
212
|
+
if (!injection.list.get(injectName || name)) {
|
|
213
|
+
injection.list.set(injectName || name, name);
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* 获取下级注入的依赖,与 Inject 一起使用
|
|
220
|
+
*
|
|
221
|
+
* @param {string|Symbol} provideName? 被注入的name,如果不传递,那么取target中的name
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
*
|
|
225
|
+
* * parent.ts * // 文件
|
|
226
|
+
*
|
|
227
|
+
* @Widget.Provide('ProvideName')
|
|
228
|
+
* private rootData!:
|
|
229
|
+
*
|
|
230
|
+
* 如果要将该值变为响应式,如果加上Reactive
|
|
231
|
+
*
|
|
232
|
+
* @Widget.Reactive()
|
|
233
|
+
* @Widget.Provide('ProvideName')
|
|
234
|
+
* private rootData!:;
|
|
235
|
+
*/
|
|
236
|
+
protected static Provide(provideName?: string | Symbol) {
|
|
237
|
+
return <T extends Widget>(target: T, name: string) => {
|
|
238
|
+
let injection: { name: typeof Widget; list: Map<string | Symbol, string> } = Reflect.get(target, 'provider') || {
|
|
239
|
+
name: this,
|
|
240
|
+
list: new Map()
|
|
241
|
+
};
|
|
242
|
+
if (injection.name !== (target.constructor as typeof Widget)) {
|
|
243
|
+
const old = injection;
|
|
244
|
+
injection = { name: target.constructor as typeof Widget, list: new Map() };
|
|
245
|
+
old.list.forEach((v, k) => injection.list.set(k, v));
|
|
246
|
+
Reflect.set(target, 'provider', injection);
|
|
247
|
+
}
|
|
248
|
+
// const injection = Reflect.get(target, 'injection') as Map<string | Symbol, string>;
|
|
249
|
+
if (!injection.list.get(provideName || name)) {
|
|
250
|
+
injection.list.set(provideName || name, name);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
private parent: Widget | null;
|
|
256
|
+
|
|
257
|
+
protected $$innerWidgetType: InnerWidgetType | null | undefined;
|
|
258
|
+
|
|
259
|
+
protected childrenInstance: Widget[] = [];
|
|
260
|
+
|
|
261
|
+
protected children: Widget[] = [];
|
|
262
|
+
|
|
263
|
+
protected childrenWidget: Widget[] = [];
|
|
264
|
+
|
|
265
|
+
private readonly handle: string;
|
|
266
|
+
|
|
267
|
+
public config: Props = {} as Props;
|
|
268
|
+
|
|
269
|
+
private name: string;
|
|
270
|
+
|
|
271
|
+
private initialized = false;
|
|
272
|
+
|
|
273
|
+
private self: Widget | null;
|
|
274
|
+
|
|
275
|
+
public constructor(handle?: string) {
|
|
276
|
+
this.parent = null;
|
|
277
|
+
this.childrenInstance = [];
|
|
278
|
+
this.handle = handle || Widget.createHandle(this.constructor.name);
|
|
279
|
+
this.name = 'default';
|
|
280
|
+
this.self = this;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
protected getSelf() {
|
|
284
|
+
return this.self;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
public getOperator() {
|
|
288
|
+
return this;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
public initialize(config: Props = {} as Props): Widget {
|
|
292
|
+
if (this.initialized) {
|
|
293
|
+
throw new Error(`error: reInitializeWidget:${this.getWidgetType()}:${this.getHandle()}`);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const props = {};
|
|
297
|
+
const injection = (Reflect.get(this, 'injection') || { list: new Map() }).list as Map<string | Symbol, string>;
|
|
298
|
+
const attrs = this.getAttributes();
|
|
299
|
+
|
|
300
|
+
if (injection) {
|
|
301
|
+
injection.forEach((name, injectName) => {
|
|
302
|
+
const shared = this.getShared(injectName);
|
|
303
|
+
if (shared.host !== undefined) {
|
|
304
|
+
Reflect.set(props, name, {
|
|
305
|
+
get: () => {
|
|
306
|
+
return this.getShared(injectName).value;
|
|
307
|
+
},
|
|
308
|
+
configurable: true
|
|
309
|
+
});
|
|
310
|
+
let displayName = '';
|
|
311
|
+
attrs.forEach((nativeName, dname) => (nativeName === name ? (displayName = dname) : ''));
|
|
312
|
+
if (displayName !== '') {
|
|
313
|
+
Reflect.set(this, `$compute$${name}`, { get: () => this.getShared(injectName).value });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
Object.defineProperties(this, props);
|
|
319
|
+
this.initialized = true;
|
|
320
|
+
this.config = config;
|
|
321
|
+
Widget.widgetMap.set(this.getHandle(), this);
|
|
322
|
+
|
|
323
|
+
Widget.nameContextMap.forEach((contextMap) => {
|
|
324
|
+
const { subject, paramName_NameMap } = contextMap;
|
|
325
|
+
const d: BaseWidgetSubjection<unknown> = {
|
|
326
|
+
subscribe: (func) => {
|
|
327
|
+
const subscription = subject.subscribe((data) => {
|
|
328
|
+
func(data);
|
|
329
|
+
});
|
|
330
|
+
this.subscriptionMap.set(Symbol('random'), subscription);
|
|
331
|
+
return subscription;
|
|
332
|
+
},
|
|
333
|
+
subject
|
|
334
|
+
};
|
|
335
|
+
paramName_NameMap.forEach((_name, paramName) => {
|
|
336
|
+
this[paramName] = d;
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
if (this.$$innerWidgetType) {
|
|
341
|
+
const parentWidget = this.getParentWidget();
|
|
342
|
+
if (parentWidget && parentWidget.$$innerWidgetType) {
|
|
343
|
+
parentWidget.childrenWidget.push(this);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return this;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* 销毁widget
|
|
352
|
+
*
|
|
353
|
+
* 内部会根据handle匹配到对应的widget,然后进行销毁,如果children中出现了相同的handle,那么会销毁第一个
|
|
354
|
+
*/
|
|
355
|
+
public dispose(force = false) {
|
|
356
|
+
this.releaseInjection();
|
|
357
|
+
const pchildren = this.parent?.children;
|
|
358
|
+
if (pchildren) {
|
|
359
|
+
const index = pchildren.findIndex((c) => c.getHandle() === this.getHandle());
|
|
360
|
+
if (index !== -1) {
|
|
361
|
+
pchildren.splice(index, 1);
|
|
362
|
+
this.parent?.childrenInstance.splice(index, 1);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
while (this.children.length) {
|
|
366
|
+
this.children[0].dispose(force);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
Widget.widgetMap.delete(this.getHandle());
|
|
370
|
+
this.subscriptionMap.forEach((subscription) => {
|
|
371
|
+
subscription.unsubscribe();
|
|
372
|
+
});
|
|
373
|
+
this.subscriptionMap.clear();
|
|
374
|
+
|
|
375
|
+
this.self = null;
|
|
376
|
+
|
|
377
|
+
this.childrenInstance = [];
|
|
378
|
+
this.children = [];
|
|
379
|
+
this.childrenWidget = [];
|
|
380
|
+
this.parent = null;
|
|
381
|
+
|
|
382
|
+
force && (this.$$props = undefined);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* 创建一个widget
|
|
387
|
+
*
|
|
388
|
+
* @param {Widget} constructor 对应的widget
|
|
389
|
+
* @param {string} name? 插槽
|
|
390
|
+
* @param {IViewProps} config? widget中initialize方法接收的参数
|
|
391
|
+
*
|
|
392
|
+
*/
|
|
393
|
+
public createWidget<T extends Widget>(
|
|
394
|
+
constructor: WidgetConstructor<T['config'], T>,
|
|
395
|
+
name?: string,
|
|
396
|
+
config?: T['config'],
|
|
397
|
+
specifiedIndex?: number
|
|
398
|
+
) {
|
|
399
|
+
const child = instantiate(constructor);
|
|
400
|
+
child.parent = this;
|
|
401
|
+
|
|
402
|
+
const widget = child.initialize(config);
|
|
403
|
+
|
|
404
|
+
const instance = widget && widget.getOperator();
|
|
405
|
+
if (specifiedIndex !== undefined && specifiedIndex >= 0) {
|
|
406
|
+
this.children[specifiedIndex] = instance;
|
|
407
|
+
} else {
|
|
408
|
+
this.children.push(instance);
|
|
409
|
+
}
|
|
410
|
+
if (name) {
|
|
411
|
+
child.name = name;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return instance as T;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
public getHandle(): HANDLE {
|
|
418
|
+
return this.handle;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* 删除指定的widget
|
|
423
|
+
*/
|
|
424
|
+
public deleteWidget(name: string): boolean {
|
|
425
|
+
const { length } = this.children;
|
|
426
|
+
this.children.forEach((c, index) => {
|
|
427
|
+
if (c.getHandle() === name) {
|
|
428
|
+
c.dispose();
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
return this.children.length !== length;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
public moveChildWidget(endIndex: number, startIndex: number) {
|
|
436
|
+
if (this.parent) {
|
|
437
|
+
this.children[endIndex] = this.children.splice(startIndex, 1, this.children[endIndex])[0];
|
|
438
|
+
this.childrenInstance[endIndex] = this.childrenInstance.splice(startIndex, 1, this.childrenInstance[endIndex])[0];
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
public insertWidget(widget: Widget, index: number) {
|
|
443
|
+
if (this.parent) {
|
|
444
|
+
this.children.splice(index, 0, widget);
|
|
445
|
+
this.childrenInstance.splice(index, 0, widget);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
public deleteWidgetByIndex(index: number, handle?: string): boolean {
|
|
450
|
+
const { length } = this.children;
|
|
451
|
+
const handler = handle || this.children[index].getHandle();
|
|
452
|
+
|
|
453
|
+
this.children.forEach((c, idx) => {
|
|
454
|
+
if (c.getHandle() === handler && idx === index) {
|
|
455
|
+
c.dispose();
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
return this.children.length !== length;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
public getConfig(key: string): unknown {
|
|
462
|
+
return this.config[key];
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
public getAllConfig() {
|
|
466
|
+
return this.config;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
public getSibling() {
|
|
470
|
+
if (!this.$$innerWidgetType) {
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const parent = this.getParentWidget();
|
|
475
|
+
|
|
476
|
+
return parent ? parent.getChildrenWidget() : null;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* 返回当前元素在其父元素的子元素节点中的前一个元素节点,如果该元素已经是第一个元素节点,则返回 null
|
|
481
|
+
*/
|
|
482
|
+
public previousWidgetSibling() {
|
|
483
|
+
const sibling = this.getSibling();
|
|
484
|
+
|
|
485
|
+
if (!sibling) {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const index = sibling.findIndex((w) => w.getHandle() === this.getHandle());
|
|
490
|
+
return index > 0 ? sibling[index - 1] : null;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* 返回当前元素在其父元素的子元素节点中的后一个元素节点,如果该元素已经是最后一个元素节点,则返回 null
|
|
495
|
+
*/
|
|
496
|
+
public nextWidgetSibling() {
|
|
497
|
+
const sibling = this.getSibling();
|
|
498
|
+
|
|
499
|
+
if (!sibling) {
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const index = sibling.findIndex((w) => w.getHandle() === this.getHandle());
|
|
504
|
+
return index >= 0 && index < sibling.length - 1 ? sibling[index + 1] : null;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* 获取父元素
|
|
509
|
+
*/
|
|
510
|
+
public getParentWidget(): Widget | null {
|
|
511
|
+
if (this.$$innerWidgetType) {
|
|
512
|
+
let parentNode = this.parent;
|
|
513
|
+
|
|
514
|
+
if (!parentNode) {
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
while (parentNode) {
|
|
519
|
+
if (parentNode.$$innerWidgetType) {
|
|
520
|
+
return parentNode;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
parentNode = parentNode.parent;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return this.parent;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* 获取子元素
|
|
532
|
+
*/
|
|
533
|
+
public getChildrenWidget() {
|
|
534
|
+
return this.childrenWidget.length ? this.childrenWidget : this.getChildrenInstance();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* @inner
|
|
539
|
+
*
|
|
540
|
+
*/
|
|
541
|
+
public getParent(): Widget | null {
|
|
542
|
+
return this.parent;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
public getName(): string {
|
|
546
|
+
return this.name;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
public getWidgetType(): string {
|
|
550
|
+
return this.constructor.name;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
public static getProtoChains<T extends Function>(obj: T): Function[] {
|
|
554
|
+
let result = Widget.protoChainsCache.get(obj);
|
|
555
|
+
if (result) {
|
|
556
|
+
return result;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
result = [];
|
|
560
|
+
let iterator = obj;
|
|
561
|
+
while (iterator.name !== '') {
|
|
562
|
+
result.push(iterator);
|
|
563
|
+
iterator = Object.getPrototypeOf(iterator);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
Widget.protoChainsCache.set(obj, result);
|
|
567
|
+
return result;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
private currentAttributeMapCache!: Map<string, string>;
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* 获取所有的属性
|
|
574
|
+
*/
|
|
575
|
+
public getAttributes(): Map<string, string> {
|
|
576
|
+
if (this.currentAttributeMapCache) {
|
|
577
|
+
return this.currentAttributeMapCache;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const chains = Widget.getProtoChains(this.constructor);
|
|
581
|
+
const attrs: Map<string, string> = new Map();
|
|
582
|
+
const excludesAttrs = new Set<string>();
|
|
583
|
+
|
|
584
|
+
chains.forEach((ctor) => {
|
|
585
|
+
const localAttrs = Widget.attributeMap.get(ctor);
|
|
586
|
+
if (localAttrs) {
|
|
587
|
+
localAttrs.forEach((displayName, nativeName) => {
|
|
588
|
+
attrs.set(nativeName, displayName);
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
return (this.currentAttributeMapCache = attrs);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* 获取所有的监听事件
|
|
598
|
+
*/
|
|
599
|
+
public getWatchers(): watcher<unknown>[] {
|
|
600
|
+
const watchers: watcher<unknown>[] = [];
|
|
601
|
+
const chains = Widget.getProtoChains(this.constructor);
|
|
602
|
+
chains.forEach((name) => {
|
|
603
|
+
const localWatchers = Widget.watchMap.get(name);
|
|
604
|
+
localWatchers && localWatchers.forEach((watcher) => watchers.push(watcher));
|
|
605
|
+
});
|
|
606
|
+
return watchers;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* @deprecated 使用 getChildrenWidget()
|
|
611
|
+
*
|
|
612
|
+
* 获取所有的children
|
|
613
|
+
*/
|
|
614
|
+
public getChildren(): Widget[] {
|
|
615
|
+
return this.children;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* @inner
|
|
620
|
+
*
|
|
621
|
+
*/
|
|
622
|
+
public getChildrenInstance(): Widget[] {
|
|
623
|
+
return this.childrenInstance;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
protected addChildrenInstance(widget: Widget) {
|
|
627
|
+
this.childrenInstance.push(widget);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
protected getShared(injectName: string | Symbol): { host?: Widget; value?: unknown } {
|
|
631
|
+
let parent = this.getParent();
|
|
632
|
+
let name = '';
|
|
633
|
+
while (parent) {
|
|
634
|
+
const provider: Map<string | Symbol, string> = (Reflect.get(parent, 'provider') || { list: new Map() }).list;
|
|
635
|
+
if (provider && provider.get(injectName)) {
|
|
636
|
+
name = provider.get(injectName)!;
|
|
637
|
+
break;
|
|
638
|
+
}
|
|
639
|
+
parent = parent.getParent();
|
|
640
|
+
}
|
|
641
|
+
if (parent) {
|
|
642
|
+
let result = Reflect.get(parent, name);
|
|
643
|
+
if (typeof result === 'function') {
|
|
644
|
+
result = result.bind(parent);
|
|
645
|
+
}
|
|
646
|
+
return { host: parent, value: result };
|
|
647
|
+
}
|
|
648
|
+
return {};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
private releaseInjection() {
|
|
652
|
+
const injection: { list: Map<string | Symbol, string> } = Reflect.get(this, 'injection');
|
|
653
|
+
if (injection) {
|
|
654
|
+
injection.list.forEach((name) => {
|
|
655
|
+
const widget = this.getSelf()!;
|
|
656
|
+
if (!widget) {
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
Reflect.deleteProperty(widget, name);
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
Reflect.set(this, 'injection', null);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
public getComputeHandler(name: string) {
|
|
667
|
+
return Reflect.get(this, `$compute$${name}`);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
protected getProps() {
|
|
671
|
+
return this.$$props || [];
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
public abstract render(...args): R;
|
|
675
|
+
}
|