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