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