@cloudbase/lowcode-builder 1.3.0 → 1.3.2
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/lib/builder/mp/util.js +2 -1
- package/lib/test.d.ts +11 -0
- package/lib/test.js +717 -0
- package/package.json +3 -3
- package/template/html/index.html.ejs +1 -1
- package/template/mp/common/weapp-component.js +4 -1
- package/template/mp/common/weapp-page.js +2 -1
- package/template/mp/common/widget.js +636 -576
- package/template/mp/package.json +1 -1
- package/template/mp/page/api.js +3 -0
|
@@ -4,104 +4,91 @@ import { getDeep, generateDataContext } from './util';
|
|
|
4
4
|
import { compLowcodes } from './weapp-component';
|
|
5
5
|
import EventEmitter from './event-emitter';
|
|
6
6
|
import lodashSet from 'lodash.set';
|
|
7
|
-
import { REPEATER } from './constant'
|
|
8
|
-
|
|
9
|
-
function basePullAt(array, indexes) {
|
|
10
|
-
let length = array ? indexes.length : 0;
|
|
11
|
-
let lastIndex = length - 1;
|
|
12
|
-
|
|
13
|
-
// eslint-disable-next-line no-plusplus
|
|
14
|
-
while (length--) {
|
|
15
|
-
let index = indexes[length];
|
|
16
|
-
let previous;
|
|
17
|
-
if (length == lastIndex || index !== previous) {
|
|
18
|
-
previous = index;
|
|
19
|
-
Array.prototype.splice.call(array, index, 1);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return array;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function remove(array, predicate) {
|
|
26
|
-
const result = [];
|
|
27
|
-
if (!array?.length) {
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
let index = -1;
|
|
31
|
-
const indexes = [];
|
|
32
|
-
const { length } = array;
|
|
33
|
-
|
|
34
|
-
while (++index < length) {
|
|
35
|
-
const value = array[index];
|
|
36
|
-
if (predicate(value, index, array)) {
|
|
37
|
-
result.push(value);
|
|
38
|
-
indexes.push(index);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
basePullAt(array, indexes);
|
|
42
|
-
return result;
|
|
43
|
-
}
|
|
7
|
+
import { REPEATER } from './constant';
|
|
44
8
|
|
|
45
9
|
/**
|
|
46
10
|
* convert widget prop to data for wxml
|
|
47
11
|
* @param {*} props
|
|
48
12
|
*/
|
|
13
|
+
const EXTRA_PROPS_MAP = [
|
|
14
|
+
/**
|
|
15
|
+
* create widgets
|
|
16
|
+
*/
|
|
17
|
+
'id',
|
|
18
|
+
'widgetType',
|
|
19
|
+
'parent',
|
|
20
|
+
'children',
|
|
21
|
+
'_scope',
|
|
22
|
+
'_disposers',
|
|
23
|
+
'_eventListeners',
|
|
24
|
+
/**
|
|
25
|
+
* mount widget api
|
|
26
|
+
*/
|
|
27
|
+
'findWidgets',
|
|
28
|
+
'getWidgetsByType',
|
|
29
|
+
'getOwnerWidget',
|
|
30
|
+
'getDom',
|
|
31
|
+
'on',
|
|
32
|
+
'off',
|
|
33
|
+
'getConfig',
|
|
34
|
+
'_getInstanceRef',
|
|
35
|
+
'_methods',
|
|
36
|
+
'_userWidget',
|
|
37
|
+
/**
|
|
38
|
+
* 其他挂载
|
|
39
|
+
*/
|
|
40
|
+
'_descendants',
|
|
41
|
+
'_forContext', // for root 挂载
|
|
42
|
+
/**
|
|
43
|
+
* widgetProps 附带值
|
|
44
|
+
*/
|
|
45
|
+
'_id',
|
|
46
|
+
'_order',
|
|
47
|
+
'classList',
|
|
48
|
+
].reduce((map, key) => {
|
|
49
|
+
map[key] = true;
|
|
50
|
+
return map;
|
|
51
|
+
}, {});
|
|
52
|
+
|
|
49
53
|
function resolveWidgetProp(props) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
data
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
'children',
|
|
65
|
-
'parent',
|
|
66
|
-
'_parentId',
|
|
67
|
-
'_ancestorId',
|
|
68
|
-
'_descendants',
|
|
69
|
-
'id',
|
|
70
|
-
'_order',
|
|
71
|
-
'_scope',
|
|
72
|
-
'_userWidget',
|
|
73
|
-
'widgetType',
|
|
74
|
-
];
|
|
75
|
-
extraProps.map((prop) => {
|
|
76
|
-
delete data[prop];
|
|
77
|
-
});
|
|
78
|
-
return data;
|
|
54
|
+
let { classList = [], ...restProps } = props;
|
|
55
|
+
const data = {};
|
|
56
|
+
Object.keys(restProps).forEach((key) => {
|
|
57
|
+
if (EXTRA_PROPS_MAP[key]) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (restProps[key] instanceof Function || restProps[key] === undefined) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
data[key] = restProps[key];
|
|
64
|
+
});
|
|
65
|
+
data.style = styleToCss(restProps.style);
|
|
66
|
+
data.className = classList.join ? classList.join(' ') : classList;
|
|
67
|
+
return data;
|
|
79
68
|
}
|
|
80
69
|
|
|
81
70
|
// widget prop -> wxml data
|
|
82
71
|
export function resolveWidgetData(props) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
72
|
+
if (!Array.isArray(props)) {
|
|
73
|
+
return resolveWidgetProp(props);
|
|
74
|
+
}
|
|
75
|
+
return props.map(resolveWidgetData);
|
|
87
76
|
}
|
|
88
77
|
|
|
89
|
-
export function createWidgets(widgetProps, dataBinds,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
retryFailedBinds(failedBinds, true);
|
|
104
|
-
return result;
|
|
78
|
+
export function createWidgets(widgetProps, dataBinds, ownerMpInst) {
|
|
79
|
+
const rootNode = createWidgetDataTree(widgetProps, dataBinds);
|
|
80
|
+
const failedBinds = [];
|
|
81
|
+
const result = createSubWidgetTree(
|
|
82
|
+
{ ownerForWidgetHolder: {} },
|
|
83
|
+
rootNode,
|
|
84
|
+
dataBinds,
|
|
85
|
+
ownerMpInst,
|
|
86
|
+
{},
|
|
87
|
+
failedBinds,
|
|
88
|
+
undefined,
|
|
89
|
+
);
|
|
90
|
+
retryFailedBinds(failedBinds, true);
|
|
91
|
+
return result;
|
|
105
92
|
}
|
|
106
93
|
|
|
107
94
|
/**
|
|
@@ -111,57 +98,81 @@ export function createWidgets(widgetProps, dataBinds, widgetHolder, ownerMpInst)
|
|
|
111
98
|
* @returns {widgets: {id1:[], id2}, rootWidget: {children: [], _disposers: [], ...otherProps}}
|
|
112
99
|
*/
|
|
113
100
|
function createSubWidgetTree(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
failedBinds = [],
|
|
122
|
-
defaultParent = { children: observable([]), _disposers: [] },
|
|
101
|
+
ctx,
|
|
102
|
+
curForNode,
|
|
103
|
+
dataBinds,
|
|
104
|
+
ownerMpInst,
|
|
105
|
+
forContext = {},
|
|
106
|
+
failedBinds = [],
|
|
107
|
+
parentWidget = { children: observable([]), _disposers: [] },
|
|
123
108
|
) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
109
|
+
const { ownerForWidgetHolder = {}, existingWidgetMap = {} } = ctx;
|
|
110
|
+
/**
|
|
111
|
+
* 不能类似web实现记录额外的 _disposers
|
|
112
|
+
* const widgetHolder = { _disposers: [] }
|
|
113
|
+
* 因为 merger-render.initMergeRenderer 里面没有特殊处理
|
|
114
|
+
*/
|
|
115
|
+
const widgetHolder = {};
|
|
116
|
+
const { lists: forLists = [] } = forContext;
|
|
117
|
+
const currentIndex = forLists[0]?.currentIndex;
|
|
118
|
+
const indexPostfix = (forContext.lists || [])
|
|
119
|
+
.slice()
|
|
120
|
+
.reverse()
|
|
121
|
+
.map(({ currentIndex }) => ID_SEPARATOR + currentIndex)
|
|
122
|
+
.join('');
|
|
123
|
+
|
|
124
|
+
// traverse down the tree to set up all widgets
|
|
125
|
+
dfsTree(
|
|
126
|
+
curForNode,
|
|
127
|
+
(node, parentNode, cache) => {
|
|
128
|
+
const parentForWidgetArr = ownerForWidgetHolder[node.id] || [];
|
|
133
129
|
const { _waForKey } = node.value;
|
|
134
130
|
const key = forContext.forItems?.[node.id]?.[_waForKey];
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
131
|
+
let forExistingWidgetMap = {};
|
|
132
|
+
let forExsitWidget;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* for 起始节点,根据 existingWidgetMap 判断复用
|
|
136
|
+
*/
|
|
137
|
+
if (node.id === curForNode.id) {
|
|
138
|
+
if (existingWidgetMap[key] && existingWidgetMap[key].index === currentIndex) {
|
|
139
|
+
forExistingWidgetMap = existingWidgetMap[key].widgets || {};
|
|
140
|
+
forExsitWidget = forExistingWidgetMap[node.id];
|
|
141
|
+
if (forExsitWidget) {
|
|
142
|
+
cache[node.id] = {
|
|
143
|
+
widgets: forExistingWidgetMap,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} else if (cache[parentNode?.id]) {
|
|
148
|
+
forExsitWidget = cache[parentNode?.id].widgets[node.id] || null;
|
|
149
|
+
if (forExsitWidget) {
|
|
150
|
+
cache[node.id] = cache[parentNode?.id];
|
|
151
|
+
}
|
|
144
152
|
}
|
|
153
|
+
const existedWidget = forExsitWidget || null;
|
|
145
154
|
|
|
146
155
|
if (node.forCount === curForNode.forCount) {
|
|
147
|
-
|
|
156
|
+
/**
|
|
157
|
+
* 同一层循环作用域内,当前节点与 curForNode(循环根节点)在同一级循环作用域中
|
|
158
|
+
* 即没有再开辟新级别的 for 循环
|
|
159
|
+
* Leaf node
|
|
160
|
+
*/
|
|
148
161
|
let w = existedWidget;
|
|
149
162
|
if (!existedWidget) {
|
|
150
163
|
const parentNode = node.parent;
|
|
151
|
-
let
|
|
152
|
-
|
|
153
|
-
parentWidget = widgetHolder[parentNode.id] || ownerForWidgetHolder[parentNode.id];
|
|
154
|
-
}
|
|
155
|
-
w = createWidget(widgetProps[node.id], node.id, indexPostfix, parentWidget, ownerMpInst, forContext.forItems?.[node.id]);
|
|
164
|
+
let parent = parentNode ? widgetHolder[parentNode.id] || ownerForWidgetHolder[parentNode.id] : null;
|
|
165
|
+
w = createWidget(node.value, node.id, indexPostfix, parent, ownerMpInst, forContext.forItems?.[node.id]);
|
|
156
166
|
w._key = key;
|
|
157
167
|
|
|
158
|
-
if (!
|
|
159
|
-
|
|
168
|
+
if (!parent) {
|
|
169
|
+
parentWidget.children.push(w);
|
|
160
170
|
}
|
|
161
|
-
parentForWidgetArr.push(w);
|
|
162
171
|
} else {
|
|
172
|
+
w.id = `${node.id}${indexPostfix}`;
|
|
163
173
|
disposeWidget(existedWidget, true);
|
|
164
174
|
}
|
|
175
|
+
parentForWidgetArr.push?.(w);
|
|
165
176
|
setUpWidgetDataBinds(w, dataBinds[node.id], forContext, failedBinds, ownerMpInst._getInstance());
|
|
166
177
|
widgetHolder[node.id] = w;
|
|
167
178
|
if (widgetHolder?.[node._ancestorId]) {
|
|
@@ -170,37 +181,47 @@ function createSubWidgetTree(
|
|
|
170
181
|
widgetHolder[node._ancestorId]._descendants = widgetHolder[node._ancestorId]._descendants || {};
|
|
171
182
|
widgetHolder[node._ancestorId]._descendants[node.id] = widgetHolder[node.id];
|
|
172
183
|
}
|
|
173
|
-
} else if (!existedWidget) {
|
|
174
|
-
const len = parentForWidgetArr.push(observable([]));
|
|
175
|
-
widgetHolder[node.id] = parentForWidgetArr[len - 1];
|
|
176
184
|
} else {
|
|
177
|
-
|
|
178
|
-
|
|
185
|
+
if (!existedWidget) {
|
|
186
|
+
widgetHolder[node.id] = observable([]);
|
|
187
|
+
} else {
|
|
188
|
+
// Reuse existed for widget array
|
|
189
|
+
widgetHolder[node.id] = existedWidget;
|
|
190
|
+
}
|
|
191
|
+
if (parentForWidgetArr) {
|
|
192
|
+
parentForWidgetArr.push(widgetHolder[node.id]);
|
|
193
|
+
}
|
|
179
194
|
}
|
|
180
|
-
}
|
|
195
|
+
},
|
|
196
|
+
undefined,
|
|
197
|
+
);
|
|
181
198
|
|
|
182
|
-
|
|
183
|
-
|
|
199
|
+
// run for of next level
|
|
200
|
+
dfsTree(
|
|
201
|
+
curForNode,
|
|
202
|
+
(node) => {
|
|
184
203
|
if (node.forCount === curForNode.forCount + 1 && dataBinds[node.id] && dataBinds[node.id]._waFor) {
|
|
185
204
|
// find the node bound with next level for
|
|
186
|
-
const parent = node
|
|
187
|
-
const dispose = runFor(node,
|
|
205
|
+
const parent = getNodeParentWidget(node, widgetHolder, parentWidget);
|
|
206
|
+
const dispose = runFor(node, dataBinds, ownerMpInst, forContext, widgetHolder, failedBinds, parent);
|
|
188
207
|
parent._disposers.push(dispose); // Add the for bind dispose to the parent node of forNode
|
|
189
208
|
}
|
|
190
|
-
}
|
|
209
|
+
},
|
|
210
|
+
undefined,
|
|
211
|
+
);
|
|
191
212
|
|
|
192
|
-
|
|
213
|
+
retryFailedBinds(failedBinds);
|
|
193
214
|
|
|
194
|
-
|
|
215
|
+
return { widgets: widgetHolder, rootWidget: widgetHolder[curForNode.id] || parentWidget };
|
|
195
216
|
}
|
|
196
217
|
|
|
197
218
|
// Retry failed databinds
|
|
198
219
|
function retryFailedBinds(failedBinds, finalTry) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
220
|
+
const len = failedBinds.length;
|
|
221
|
+
for (let i = 0; i < len; i++) {
|
|
222
|
+
const setUpDataBind = failedBinds.shift();
|
|
223
|
+
setUpDataBind(finalTry);
|
|
224
|
+
}
|
|
204
225
|
}
|
|
205
226
|
|
|
206
227
|
/**
|
|
@@ -212,540 +233,579 @@ function retryFailedBinds(failedBinds, finalTry) {
|
|
|
212
233
|
* @returns top level widgets or for dispose
|
|
213
234
|
*/
|
|
214
235
|
const _FOR_ERROR_CACHE_MAP = {};
|
|
215
|
-
function runFor(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
forList = dataBinds[nodeId]._waFor.call(
|
|
239
|
-
$instance,
|
|
240
|
-
$instance,
|
|
241
|
-
forContext.lists,
|
|
242
|
-
forContext.forItems,
|
|
243
|
-
undefined,
|
|
244
|
-
dataContext,
|
|
245
|
-
$w,
|
|
246
|
-
);
|
|
247
|
-
if (!Array.isArray(forList)) {
|
|
248
|
-
forList = [];
|
|
249
|
-
}
|
|
250
|
-
} catch (e) {
|
|
236
|
+
function runFor(curForNode, dataBinds, ownerMpInst, forContext, ownerForWidgetHolder, failedBinds, parentWidget) {
|
|
237
|
+
const nodeId = curForNode.id;
|
|
238
|
+
const { _waForKey } = curForNode.value;
|
|
239
|
+
|
|
240
|
+
const dispose = autorun(() => {
|
|
241
|
+
let forList = [];
|
|
242
|
+
try {
|
|
243
|
+
clearTimeout(_FOR_ERROR_CACHE_MAP[nodeId]);
|
|
244
|
+
|
|
245
|
+
const $instance = ownerMpInst._getInstance();
|
|
246
|
+
const dataContext = untracked(() => generateDataContext(parentWidget));
|
|
247
|
+
const $w = untracked(() => generateWidgetAPIContext($instance?.__internal__?.$w, parentWidget, forContext));
|
|
248
|
+
|
|
249
|
+
forList = dataBinds[nodeId]._waFor.call(
|
|
250
|
+
$instance,
|
|
251
|
+
$instance,
|
|
252
|
+
forContext.lists,
|
|
253
|
+
forContext.forItems,
|
|
254
|
+
undefined,
|
|
255
|
+
dataContext,
|
|
256
|
+
$w,
|
|
257
|
+
);
|
|
258
|
+
if (!Array.isArray(forList)) {
|
|
251
259
|
forList = [];
|
|
252
|
-
_FOR_ERROR_CACHE_MAP[nodeId] = setTimeout(() => {
|
|
253
|
-
console.warn('For binding error', nodeId, e);
|
|
254
|
-
}, 1000);
|
|
255
260
|
}
|
|
261
|
+
} catch (e) {
|
|
262
|
+
forList = [];
|
|
263
|
+
_FOR_ERROR_CACHE_MAP[nodeId] = setTimeout(() => {
|
|
264
|
+
console.warn('For binding error', nodeId, e);
|
|
265
|
+
}, 1000);
|
|
266
|
+
}
|
|
256
267
|
|
|
257
|
-
|
|
258
|
-
|
|
268
|
+
// Track list change (e.g. push)
|
|
269
|
+
forList.forEach((e) => {});
|
|
259
270
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const arr = ownerForWidgetHolder[node.id];
|
|
291
|
-
remove(arr, (_, index) => {
|
|
292
|
-
return extraWidgetsIndexMap[index];
|
|
293
|
-
});
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
// 清理根 for 的 autorun, 并递归清理子节点
|
|
297
|
-
extraWidgets.map((w) => {
|
|
298
|
-
disposeWidget(w);
|
|
299
|
-
const { children } = w.parent || defaultParent;
|
|
300
|
-
children.remove(w);
|
|
301
|
-
// w.parent = null
|
|
302
|
-
});
|
|
271
|
+
untracked(() => {
|
|
272
|
+
// dispose widgets before reused instead
|
|
273
|
+
// disposeWidgets(parentForWidgets[curForNode.id])
|
|
274
|
+
const exsitMap = forList.reduce((map, item, index) => {
|
|
275
|
+
const cache = item?.[_waForKey];
|
|
276
|
+
if (map[cache] === undefined) {
|
|
277
|
+
map[cache] = index;
|
|
278
|
+
}
|
|
279
|
+
return map;
|
|
280
|
+
}, {});
|
|
281
|
+
const forWidgets = ownerForWidgetHolder[nodeId];
|
|
282
|
+
const existingWidgetMap = {};
|
|
283
|
+
const existingWidgetIndexMap = {};
|
|
284
|
+
const extraWidgetsIndexMap = {};
|
|
285
|
+
forWidgets.forEach((widget, index) => {
|
|
286
|
+
if (exsitMap[widget._key] !== undefined) {
|
|
287
|
+
const nodeId = widget.id?.split(ID_SEPARATOR)[0];
|
|
288
|
+
existingWidgetMap[widget._key] = { index: exsitMap[widget._key], widgets: { [nodeId]: widget } };
|
|
289
|
+
/**
|
|
290
|
+
* 此处依赖了 existingWidgetMap[widget._key].widgets 的引用,
|
|
291
|
+
* 为了直接可以通过 index 访问到 existingWidgetMap 里的值进行编辑
|
|
292
|
+
* 但是依赖引用关系,存在维护风险
|
|
293
|
+
*/
|
|
294
|
+
existingWidgetIndexMap[index] = existingWidgetMap[widget._key].widgets;
|
|
295
|
+
// need to use uqique key
|
|
296
|
+
exsitMap[widget._key] = undefined;
|
|
297
|
+
} else {
|
|
298
|
+
extraWidgetsIndexMap[index] = widget;
|
|
299
|
+
}
|
|
300
|
+
});
|
|
303
301
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
302
|
+
// clean extra widgets of previous for run
|
|
303
|
+
dfsTree(
|
|
304
|
+
curForNode,
|
|
305
|
+
(node) => {
|
|
306
|
+
const arr = ownerForWidgetHolder[node.id] || [];
|
|
307
|
+
/**
|
|
308
|
+
* clone 上次 for 已有的 widgets
|
|
309
|
+
*/
|
|
310
|
+
if (node.id !== curForNode.id) {
|
|
311
|
+
arr.forEach((item, index) => {
|
|
312
|
+
if (existingWidgetIndexMap[index]) {
|
|
313
|
+
existingWidgetIndexMap[index][node.id] = item;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
315
316
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
317
|
+
/**
|
|
318
|
+
* 重头开始生成
|
|
319
|
+
* 清空原有 arr 并保持引用不变
|
|
320
|
+
*/
|
|
321
|
+
arr.splice(0, arr.length);
|
|
322
|
+
},
|
|
323
|
+
undefined,
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* 明确已经不会复用的节点,清除 mobx observer
|
|
328
|
+
* 并递归清理子节点
|
|
329
|
+
*/
|
|
330
|
+
for (const index in extraWidgetsIndexMap) {
|
|
331
|
+
const w = extraWidgetsIndexMap[index];
|
|
332
|
+
disposeWidget(w);
|
|
333
|
+
const { children } = w.parent || parentWidget;
|
|
334
|
+
children.remove(w);
|
|
335
|
+
// w.parent = null
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const isInRepeaterChild = parentWidget?.widgetType === `${REPEATER.MODULE_NAME}:${REPEATER.REPEATER_NAME}`;
|
|
339
|
+
forList.forEach((item, index) => {
|
|
340
|
+
let forContextListAlias;
|
|
341
|
+
let { lists = [], forItems = {} } = forContext;
|
|
342
|
+
const listMeta = { currentItem: item, currentIndex: index };
|
|
343
|
+
if (isInRepeaterChild) {
|
|
344
|
+
forContextListAlias = {
|
|
345
|
+
[`${parentWidget.forIndex}` || 'currentIndex']: listMeta.currentIndex,
|
|
346
|
+
[`${parentWidget.forItem}` || 'currentItem']: listMeta.currentItem,
|
|
319
347
|
};
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
348
|
+
}
|
|
349
|
+
const _forContext = {
|
|
350
|
+
lists: [{ ...listMeta, alias: forContextListAlias }, ...lists],
|
|
351
|
+
forItems: { ...forItems, [nodeId]: item },
|
|
352
|
+
};
|
|
353
|
+
const { rootWidget } = createSubWidgetTree(
|
|
354
|
+
{ ownerForWidgetHolder, existingWidgetMap },
|
|
355
|
+
curForNode,
|
|
356
|
+
dataBinds,
|
|
357
|
+
ownerMpInst,
|
|
358
|
+
_forContext,
|
|
359
|
+
failedBinds,
|
|
360
|
+
parentWidget,
|
|
361
|
+
);
|
|
362
|
+
rootWidget._forContext = _forContext;
|
|
333
363
|
});
|
|
334
364
|
});
|
|
365
|
+
});
|
|
335
366
|
|
|
336
|
-
|
|
367
|
+
return dispose;
|
|
337
368
|
}
|
|
338
369
|
|
|
339
370
|
function createWidget(props, nodeId, indexPostfix, parent, ownerMpInst, forContext) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
371
|
+
const { widgetType, _parentId, ...restProps } = props;
|
|
372
|
+
const w = observable(restProps);
|
|
373
|
+
const id = `${nodeId}${indexPostfix}`;
|
|
374
|
+
|
|
375
|
+
// Builtin props
|
|
376
|
+
w.id = id; // 重用之后要修改id
|
|
377
|
+
// Object.defineProperty(w, 'id', { value: id });
|
|
378
|
+
Object.defineProperty(w, 'widgetType', { value: widgetType });
|
|
379
|
+
Object.defineProperty(w, '_scope', {
|
|
380
|
+
value: observable({
|
|
381
|
+
id: nodeId,
|
|
382
|
+
dataContext: {},
|
|
383
|
+
/**
|
|
384
|
+
* 当前节点的 for currentItem 对象
|
|
385
|
+
*/
|
|
386
|
+
forContext,
|
|
387
|
+
}),
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// w._disposers = []
|
|
391
|
+
// w.children = []
|
|
392
|
+
Object.defineProperty(w, 'children', { value: observable([]) });
|
|
393
|
+
Object.defineProperty(w, '_disposers', { value: observable([]) });
|
|
394
|
+
Object.defineProperty(w, '_eventListeners', { value: new EventEmitter() });
|
|
395
|
+
if (parent) {
|
|
396
|
+
// w.parent = parent
|
|
397
|
+
Object.defineProperty(w, 'parent', { value: parent });
|
|
398
|
+
parent.children.push(w);
|
|
399
|
+
}
|
|
365
400
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
});
|
|
376
|
-
return descendants;
|
|
401
|
+
switch (widgetType) {
|
|
402
|
+
case `${REPEATER.MODULE_NAME}:${REPEATER.REPEATER_NAME}`: {
|
|
403
|
+
if (!w.items) {
|
|
404
|
+
Object.defineProperty(w, 'items', {
|
|
405
|
+
get() {
|
|
406
|
+
return (w.children || []).map((item) => {
|
|
407
|
+
const descendants = {};
|
|
408
|
+
Object.keys(item?._descendants || {}).forEach((key) => {
|
|
409
|
+
descendants[key] = item._descendants[key]._userWidget;
|
|
377
410
|
});
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
411
|
+
return descendants;
|
|
412
|
+
});
|
|
413
|
+
},
|
|
414
|
+
});
|
|
382
415
|
}
|
|
416
|
+
break;
|
|
383
417
|
}
|
|
418
|
+
}
|
|
384
419
|
|
|
385
|
-
|
|
386
|
-
|
|
420
|
+
mountBuiltinWigetsAPI(w, ownerMpInst);
|
|
421
|
+
return w;
|
|
387
422
|
}
|
|
388
423
|
|
|
389
424
|
function setUpWidgetDataBinds(w, dataBinds, forContext, failedBinds, ctx) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
425
|
+
Object.keys(dataBinds || {})
|
|
426
|
+
.sort((a, b) => {
|
|
427
|
+
return a.length - b.length > 0 ? 1 : -1;
|
|
428
|
+
})
|
|
429
|
+
.map((prop) => {
|
|
430
|
+
if (prop === '_waFor') {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
let timer = null;
|
|
434
|
+
const setUpDataBind = (isFinalTry) => {
|
|
435
|
+
let ran = false;
|
|
436
|
+
const dispose = autorun((reaction) => {
|
|
437
|
+
try {
|
|
438
|
+
clearTimeout(timer);
|
|
439
|
+
|
|
440
|
+
const dataContext = untracked(() => generateDataContext(w));
|
|
441
|
+
const $w = untracked(() => generateWidgetAPIContext(ctx?.__internal__?.$w, w, forContext));
|
|
442
|
+
|
|
443
|
+
// Computed data bind in the next tick since data bind may read widgets data
|
|
444
|
+
const value = dataBinds[prop].call(
|
|
445
|
+
ctx,
|
|
446
|
+
ctx,
|
|
447
|
+
forContext.lists,
|
|
448
|
+
forContext.forItems,
|
|
449
|
+
undefined,
|
|
450
|
+
dataContext,
|
|
451
|
+
$w,
|
|
452
|
+
);
|
|
453
|
+
const paths = prop.split('.').filter((key) => !!key);
|
|
454
|
+
if (paths.length > 1) {
|
|
455
|
+
// 一定要 untracked 不然爆栈了
|
|
456
|
+
untracked(() => lodashSet(w, prop, value));
|
|
457
|
+
} else {
|
|
458
|
+
// 普通 key 直接赋值
|
|
459
|
+
w[prop] = value;
|
|
460
|
+
}
|
|
461
|
+
} catch (e) {
|
|
462
|
+
if (prop === '_waIf') {
|
|
463
|
+
w[prop] = false;
|
|
464
|
+
}
|
|
430
465
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
466
|
+
if (isFinalTry || ran) {
|
|
467
|
+
timer = setTimeout(() => {
|
|
468
|
+
console.warn(`Error computing data bind ${w.id}.${prop}`, e);
|
|
469
|
+
}, 1000);
|
|
470
|
+
} else {
|
|
471
|
+
failedBinds.push((...args) => {
|
|
436
472
|
reaction.dispose();
|
|
437
|
-
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
ran = true;
|
|
473
|
+
return setUpDataBind(...args);
|
|
474
|
+
});
|
|
441
475
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
476
|
+
|
|
477
|
+
ran = true;
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
w._disposers.push(dispose);
|
|
481
|
+
};
|
|
482
|
+
setUpDataBind();
|
|
483
|
+
});
|
|
447
484
|
}
|
|
448
485
|
|
|
449
486
|
export function generateForContextOfWidget(widget) {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
487
|
+
const forContext = widget._forContext;
|
|
488
|
+
if (forContext) return forContext;
|
|
489
|
+
if (widget.parent) return generateForContextOfWidget(widget.parent);
|
|
453
490
|
}
|
|
454
491
|
|
|
455
492
|
export const ID_SEPARATOR = '-';
|
|
456
493
|
export function getWidget(widgets, id) {
|
|
457
|
-
|
|
494
|
+
return getDeep(widgets, id, ID_SEPARATOR);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function getNodeParentWidget(node, widgets, defaultParent = { children: observable([]), _disposers: [] }) {
|
|
498
|
+
return (node?.parent?.id && widgets?.[node.parent.id]) || defaultParent;
|
|
458
499
|
}
|
|
459
500
|
|
|
460
501
|
/**
|
|
461
502
|
* Add parent, children to widget
|
|
462
503
|
*/
|
|
463
504
|
function createWidgetDataTree(widgets, dataBinds) {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
505
|
+
const virtualRoot = { children: [], forCount: 0 };
|
|
506
|
+
const nodes = Object.keys(widgets).reduce((result, id) => {
|
|
507
|
+
const w = widgets[id];
|
|
508
|
+
result[id] = { id, value: w, _order: w._order, children: [], parent: null, forCount: 0 };
|
|
509
|
+
return result;
|
|
510
|
+
}, {});
|
|
511
|
+
|
|
512
|
+
// Create widgets tree API
|
|
513
|
+
Object.keys(nodes).map((id) => {
|
|
514
|
+
const curNode = nodes[id];
|
|
515
|
+
const parent = nodes[widgets[id]._parentId];
|
|
516
|
+
// delete widgets[id]._parentId
|
|
517
|
+
if (!parent) {
|
|
518
|
+
virtualRoot.children.push(curNode);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
curNode.parent = parent;
|
|
522
|
+
parent.children.push(curNode);
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// Sort children
|
|
526
|
+
Object.keys(nodes).map((id) => {
|
|
527
|
+
nodes[id].children.sort((a, b) => a._order - b._order);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
virtualRoot.children.map(addForCount);
|
|
531
|
+
|
|
532
|
+
// dfs, add forCount
|
|
533
|
+
function addForCount(node) {
|
|
534
|
+
if (node.parent) {
|
|
535
|
+
node.forCount = node.parent.forCount;
|
|
536
|
+
const { widgetType } = node.parent.value;
|
|
537
|
+
if (widgetType === `${REPEATER.MODULE_NAME}:${REPEATER.REPEATER_ITEM_NAME}`) {
|
|
538
|
+
node._ancestorId = node.parent.id;
|
|
479
539
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
// Sort children
|
|
485
|
-
Object.keys(nodes).map((id) => {
|
|
486
|
-
nodes[id].children.sort((a, b) => a._order - b._order);
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
virtualRoot.children.map(addForCount);
|
|
490
|
-
|
|
491
|
-
// dfs, add forCount
|
|
492
|
-
function addForCount(node) {
|
|
493
|
-
if (node.parent) {
|
|
494
|
-
node.forCount = node.parent.forCount;
|
|
495
|
-
const { widgetType } = node.parent.value;
|
|
496
|
-
if (widgetType === `${REPEATER.MODULE_NAME}:${REPEATER.REPEATER_ITEM_NAME}`) {
|
|
497
|
-
node._ancestorId = node.parent.id;
|
|
498
|
-
}
|
|
499
|
-
if (node.parent?._ancestorId) {
|
|
500
|
-
// Repeater 作用域内的所有子孙(排除里面的 Repeater 组件,它本身又产生深一层的作用域)继承父级的循环信息
|
|
501
|
-
if (!node._ancestorId) {
|
|
502
|
-
node._ancestorId = node.parent._ancestorId;
|
|
503
|
-
}
|
|
540
|
+
if (node.parent?._ancestorId) {
|
|
541
|
+
// Repeater 作用域内的所有子孙(排除里面的 Repeater 组件,它本身又产生深一层的作用域)继承父级的循环信息
|
|
542
|
+
if (!node._ancestorId) {
|
|
543
|
+
node._ancestorId = node.parent._ancestorId;
|
|
504
544
|
}
|
|
505
545
|
}
|
|
506
|
-
if (dataBinds[node.id]?._waFor) {
|
|
507
|
-
node.forCount += 1;
|
|
508
|
-
}
|
|
509
|
-
node.children.map(addForCount);
|
|
510
546
|
}
|
|
547
|
+
if (dataBinds[node.id]?._waFor) {
|
|
548
|
+
node.forCount += 1;
|
|
549
|
+
}
|
|
550
|
+
node.children.map(addForCount);
|
|
551
|
+
}
|
|
511
552
|
|
|
512
|
-
|
|
553
|
+
return virtualRoot;
|
|
513
554
|
}
|
|
514
555
|
|
|
515
556
|
function dfsTree(node, fn, parent, cache = {}) {
|
|
516
|
-
|
|
517
|
-
|
|
557
|
+
node.value && fn(node, parent, cache);
|
|
558
|
+
node.children.map((e) => dfsTree(e, fn, node.value ? node : null, cache));
|
|
518
559
|
}
|
|
519
560
|
|
|
520
561
|
// dispose autorun, widget can be the virtual root widget
|
|
521
|
-
export function disposeWidget(widget, noRecursive) {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
562
|
+
export function disposeWidget(widget, noRecursive = false) {
|
|
563
|
+
const disposers = widget._disposers;
|
|
564
|
+
disposers.map((dispose) => dispose());
|
|
565
|
+
disposers.splice(0, disposers.length);
|
|
566
|
+
!noRecursive && widget.children.forEach((w) => disposeWidget(w));
|
|
526
567
|
}
|
|
527
568
|
|
|
528
569
|
export function createInitData(widgets, dataBinds, keyPrefix = '') {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
570
|
+
return Object.keys(widgets).reduce((result, id) => {
|
|
571
|
+
if (!isWidgetInFor(id, widgets, dataBinds)) {
|
|
572
|
+
result[keyPrefix + id] = resolveWidgetData(widgets[id]);
|
|
573
|
+
} else {
|
|
574
|
+
result[keyPrefix + id] = [];
|
|
575
|
+
}
|
|
576
|
+
return result;
|
|
577
|
+
}, {});
|
|
537
578
|
}
|
|
538
579
|
|
|
539
580
|
function isWidgetInFor(id, widgets, dataBinds) {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
nodeId = curNode._parentId;
|
|
547
|
-
curNode = widgets[nodeId];
|
|
581
|
+
let curNode = widgets[id];
|
|
582
|
+
let nodeId = id;
|
|
583
|
+
while (curNode) {
|
|
584
|
+
if (dataBinds[nodeId]?._waFor) {
|
|
585
|
+
return true;
|
|
548
586
|
}
|
|
587
|
+
nodeId = curNode._parentId;
|
|
588
|
+
curNode = widgets[nodeId];
|
|
589
|
+
}
|
|
549
590
|
}
|
|
550
591
|
|
|
551
592
|
function mountBuiltinWigetsAPI(widget, owner) {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
593
|
+
// #1 builtin APIs
|
|
594
|
+
widget.findWidgets = function (filter, includeInvisibleDescendants) {
|
|
595
|
+
let { children = [] } = this;
|
|
596
|
+
if (!includeInvisibleDescendants) {
|
|
597
|
+
// include visible widgets only by default
|
|
598
|
+
children = children.filter((e) => e._waIf !== false);
|
|
599
|
+
}
|
|
600
|
+
const matched = [];
|
|
601
|
+
children.forEach((w) => {
|
|
602
|
+
if (filter(w)) {
|
|
603
|
+
matched.push(w);
|
|
558
604
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
}
|
|
564
|
-
matched.push(...w.findWidgets(filter, includeInvisibleDescendants));
|
|
565
|
-
});
|
|
566
|
-
return matched;
|
|
567
|
-
};
|
|
568
|
-
|
|
569
|
-
widget.getWidgetsByType = function (type, includeInvisibleDescendants) {
|
|
570
|
-
return this.findWidgets((w) => w.widgetType === type, includeInvisibleDescendants);
|
|
571
|
-
};
|
|
605
|
+
matched.push(...w.findWidgets(filter, includeInvisibleDescendants));
|
|
606
|
+
});
|
|
607
|
+
return matched;
|
|
608
|
+
};
|
|
572
609
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
widget.getOwnerWidget = function () {
|
|
577
|
-
return owner?._getInstance?.()?.node;
|
|
578
|
-
};
|
|
610
|
+
widget.getWidgetsByType = function (type, includeInvisibleDescendants) {
|
|
611
|
+
return this.findWidgets((w) => w.widgetType === type, includeInvisibleDescendants);
|
|
612
|
+
};
|
|
579
613
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
614
|
+
/**
|
|
615
|
+
* Similar to selectOwnerComponent of WX MP: https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html
|
|
616
|
+
*/
|
|
617
|
+
widget.getOwnerWidget = function () {
|
|
618
|
+
return owner?._getInstance?.()?.node;
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
// Will be overwritten by composited component
|
|
622
|
+
widget.getDom = function (fields) {
|
|
623
|
+
return new Promise((resolve, reject) => {
|
|
624
|
+
const query = (owner || wx).createSelectorQuery();
|
|
625
|
+
query
|
|
626
|
+
.select(`#${this.id}`)
|
|
627
|
+
.fields(fields, (res) => {
|
|
628
|
+
resolve(res);
|
|
629
|
+
})
|
|
630
|
+
.exec();
|
|
631
|
+
});
|
|
632
|
+
};
|
|
592
633
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
634
|
+
widget.on = function (type, listener) {
|
|
635
|
+
this._eventListeners.on(type, listener);
|
|
636
|
+
};
|
|
596
637
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
638
|
+
widget.off = function (type, listener) {
|
|
639
|
+
this._eventListeners.off(type, listener);
|
|
640
|
+
};
|
|
600
641
|
|
|
601
|
-
|
|
642
|
+
widget.getConfig = () => ({});
|
|
602
643
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
644
|
+
const lowcode = compLowcodes[widget.widgetType];
|
|
645
|
+
if (lowcode) {
|
|
646
|
+
const { config } = lowcode;
|
|
647
|
+
widget.getConfig = () => config;
|
|
648
|
+
}
|
|
608
649
|
|
|
609
|
-
|
|
650
|
+
widget._getInstanceRef = () => null;
|
|
610
651
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
652
|
+
/**
|
|
653
|
+
* @deprecated
|
|
654
|
+
*/
|
|
655
|
+
widget._methods = {};
|
|
615
656
|
|
|
616
|
-
|
|
657
|
+
Object.defineProperty(widget, '_userWidget', {
|
|
658
|
+
value: untracked(() => {
|
|
617
659
|
return new UserWidget(widget);
|
|
618
|
-
})
|
|
660
|
+
}),
|
|
661
|
+
});
|
|
619
662
|
}
|
|
620
663
|
|
|
621
664
|
/**
|
|
622
665
|
* 对外(用户)的 Widget
|
|
623
666
|
*/
|
|
624
667
|
class UserWidget {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
668
|
+
_widget = null;
|
|
669
|
+
|
|
670
|
+
get description() {
|
|
671
|
+
const { id } = this._widget;
|
|
672
|
+
return `
|
|
673
|
+
使用说明:
|
|
674
|
+
1. w 命名空间下为内置方法,可通过 $w.${id}.w.<成员> 或 $w.${id}.<成员> 访问。
|
|
675
|
+
访问 id 示例: $w.${id}.id 或 $w.${id}.w.id
|
|
676
|
+
2. custom 命名空间下为用户自定义对外暴露的成员,可通过 $w.${id}.custom.<成员> 或 $w.${id}.<成员> 访问。
|
|
677
|
+
访问自定义方法 hello 示例: $w.${id}.hello() 或 $w.${id}.custom.hello()
|
|
678
|
+
3. 通过 $w.${id}.<成员> 访问时,如果自定义成员与内置成员重名,则自定义成员覆盖内置成员。
|
|
679
|
+
4. [注意]: 请不要直接访问 _widget,它里面的成员为内部实现,随时可能进行调整
|
|
680
|
+
`;
|
|
681
|
+
}
|
|
639
682
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
683
|
+
constructor(widget) {
|
|
684
|
+
this._widget = widget;
|
|
685
|
+
return new Proxy(this, {
|
|
686
|
+
get(target, prop) {
|
|
687
|
+
if (prop in target) {
|
|
688
|
+
return target[prop];
|
|
689
|
+
}
|
|
647
690
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
691
|
+
// 优先 custom
|
|
692
|
+
if (target.custom[prop]) {
|
|
693
|
+
return target.custom[prop];
|
|
694
|
+
}
|
|
652
695
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
696
|
+
// 再尝试内置的方法和属性
|
|
697
|
+
const buildinMember = target.sys[prop];
|
|
698
|
+
if (buildinMember) return buildinMember;
|
|
656
699
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
700
|
+
// 兼容原来的 widget。最后直接代理到 widget 上,主要是访问组件的属性
|
|
701
|
+
return target._widget[prop];
|
|
702
|
+
},
|
|
703
|
+
});
|
|
704
|
+
}
|
|
662
705
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
706
|
+
// 内置属性和方法命名空间
|
|
707
|
+
get sys() {
|
|
708
|
+
const widget = this._widget;
|
|
709
|
+
const [module, component] = widget.widgetType?.split?.(':') || [];
|
|
710
|
+
return {
|
|
711
|
+
/**
|
|
712
|
+
* 内置属性
|
|
713
|
+
*/
|
|
714
|
+
|
|
715
|
+
get id() {
|
|
716
|
+
return widget.id;
|
|
717
|
+
},
|
|
670
718
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
719
|
+
get module() {
|
|
720
|
+
return module;
|
|
721
|
+
},
|
|
674
722
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
723
|
+
get component() {
|
|
724
|
+
return component;
|
|
725
|
+
},
|
|
678
726
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
727
|
+
get name() {
|
|
728
|
+
return widget.widgetType;
|
|
729
|
+
},
|
|
682
730
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
731
|
+
get parent() {
|
|
732
|
+
return widget.parent?._userWidget;
|
|
733
|
+
},
|
|
686
734
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
735
|
+
get children() {
|
|
736
|
+
return widget.children?.map((item) => item._userWidget) || [];
|
|
737
|
+
},
|
|
690
738
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
739
|
+
/**
|
|
740
|
+
* 内置方法
|
|
741
|
+
*/
|
|
694
742
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
743
|
+
closest(filter) {
|
|
744
|
+
let { parent } = this;
|
|
745
|
+
if (!filter) return parent;
|
|
698
746
|
|
|
699
|
-
|
|
700
|
-
|
|
747
|
+
while (parent) {
|
|
748
|
+
const matched = filter(parent);
|
|
749
|
+
if (matched) return parent;
|
|
701
750
|
|
|
702
|
-
|
|
703
|
-
}
|
|
704
|
-
};
|
|
705
|
-
}
|
|
751
|
+
parent = parent.parent;
|
|
752
|
+
}
|
|
706
753
|
|
|
707
|
-
|
|
708
|
-
|
|
754
|
+
return null;
|
|
755
|
+
},
|
|
709
756
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
757
|
+
/**
|
|
758
|
+
* 为了兼容 2.17+ button 组件,使用 $node.parent.getConfig
|
|
759
|
+
* 挂载代理
|
|
760
|
+
*/
|
|
761
|
+
getConfig(...args) {
|
|
762
|
+
return widget.getConfig?.(...args);
|
|
763
|
+
},
|
|
764
|
+
};
|
|
765
|
+
}
|
|
715
766
|
|
|
716
|
-
|
|
717
|
-
}
|
|
767
|
+
get custom() {
|
|
768
|
+
const { methods = {}, ...restInstance } = this._widget._getInstanceRef?.()?.current || {};
|
|
769
|
+
|
|
770
|
+
const userCustomMember = {
|
|
771
|
+
...this._widget._methods,
|
|
772
|
+
...restInstance,
|
|
773
|
+
...methods,
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
return userCustomMember;
|
|
777
|
+
}
|
|
718
778
|
}
|
|
719
779
|
|
|
720
780
|
export function generateWidgetAPIContext($w = {}, widget, forContext) {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
}
|
|
781
|
+
return new Proxy($w, {
|
|
782
|
+
get(target, prop) {
|
|
783
|
+
// debugger;
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* for context 变量优先
|
|
787
|
+
*/
|
|
788
|
+
const { lists = [] } = forContext;
|
|
789
|
+
for (const meta of lists) {
|
|
790
|
+
const map = meta.alias || {};
|
|
791
|
+
if (prop in map) {
|
|
792
|
+
return map[prop];
|
|
734
793
|
}
|
|
794
|
+
}
|
|
735
795
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}
|
|
743
|
-
parent = parent.parent;
|
|
796
|
+
// 尝试代理同级 widget
|
|
797
|
+
if (widget) {
|
|
798
|
+
let { parent } = widget;
|
|
799
|
+
while (parent) {
|
|
800
|
+
if (parent._descendants?.[prop]) {
|
|
801
|
+
return parent._descendants[prop]._userWidget;
|
|
744
802
|
}
|
|
803
|
+
parent = parent.parent;
|
|
745
804
|
}
|
|
805
|
+
}
|
|
746
806
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
807
|
+
// 尝试代理到全局的 $w
|
|
808
|
+
return target[prop];
|
|
809
|
+
},
|
|
810
|
+
});
|
|
751
811
|
}
|