@cloudbase/framework-plugin-low-code 0.7.23 → 1.0.1
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/generate.d.ts +1 -2
- package/lib/generate.d.ts.map +1 -1
- package/lib/generate.js +4 -5
- package/lib/index.d.ts +4 -7
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +94 -136
- package/lib/utils/dataSource.d.ts +0 -4
- package/lib/utils/dataSource.d.ts.map +1 -1
- package/lib/utils/dataSource.js +12 -27
- package/lib/utils/postProcess.d.ts.map +1 -1
- package/package.json +4 -3
- package/template/html/index.html.ejs +1 -1
- package/template/mp/app/app-global.js +0 -4
- package/template/mp/app/common.js +0 -26
- package/template/mp/app/handlers.js +0 -15
- package/template/mp/app/weapps-api.js +0 -89
- package/template/mp/app.js +0 -114
- package/template/mp/app.json +0 -1
- package/template/mp/app.wxss +0 -15
- package/template/mp/common/data-patch-test.js +0 -60
- package/template/mp/common/data-patch.js +0 -44
- package/template/mp/common/merge-renderer.js +0 -67
- package/template/mp/common/process.js +0 -1
- package/template/mp/common/style.js +0 -34
- package/template/mp/common/url.js +0 -21
- package/template/mp/common/util.js +0 -395
- package/template/mp/common/utils.wxs +0 -11
- package/template/mp/common/weapp-component.js +0 -250
- package/template/mp/common/weapp-page.js +0 -204
- package/template/mp/common/weapp-sdk.js +0 -76
- package/template/mp/common/widget.js +0 -381
- package/template/mp/common/wx_yypt_report_v2.js +0 -460
- package/template/mp/component/index.js +0 -66
- package/template/mp/component/index.json +0 -4
- package/template/mp/component/index.wxml +0 -1
- package/template/mp/component/index.wxss +0 -1
- package/template/mp/datasources/config.js.tpl +0 -25
- package/template/mp/datasources/dataset-profiles.js.tpl +0 -5
- package/template/mp/datasources/datasource-profiles.js.tpl +0 -4
- package/template/mp/datasources/index.js +0 -31
- package/template/mp/package.json +0 -17
- package/template/mp/page/api.js +0 -1
- package/template/mp/page/index.js +0 -42
- package/template/mp/page/index.json +0 -3
- package/template/mp/page/index.wxml +0 -1
- package/template/mp/page/index.wxss +0 -3
- package/template/mp/project.config.json +0 -1
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import { observable } from 'mobx';
|
|
2
|
-
import { createComputed, createEventHandlers, checkAuth } from './util';
|
|
3
|
-
import { createWidgets, createInitData, disposeWidget } from './widget';
|
|
4
|
-
import mergeRenderer from './merge-renderer';
|
|
5
|
-
import { createDataset, EXTRA_API, createStateDataSourceVar, generateParamsParser, setConfig } from '../datasources/index';
|
|
6
|
-
import lodashGet from 'lodash.get';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export function createPage(
|
|
10
|
-
lifecycle,
|
|
11
|
-
widgetProps,
|
|
12
|
-
pageState,
|
|
13
|
-
pageComputed,
|
|
14
|
-
evtListeners,
|
|
15
|
-
dataBinds,
|
|
16
|
-
app,
|
|
17
|
-
$page,
|
|
18
|
-
context,
|
|
19
|
-
pageAttributes
|
|
20
|
-
) {
|
|
21
|
-
const evtHandlers = createEventHandlers(evtListeners, context);
|
|
22
|
-
|
|
23
|
-
function extractLifecyles() {
|
|
24
|
-
const result = { ...lifecycle };
|
|
25
|
-
const nameMaps = [
|
|
26
|
-
['onReady', 'onPageReady'],
|
|
27
|
-
];
|
|
28
|
-
nameMaps.forEach(e => {
|
|
29
|
-
if (!result[e[0]] && result[e[1]]) {
|
|
30
|
-
result[e[0]] = result[e[1]];
|
|
31
|
-
delete result[e[1]];
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
result['onShareAppMessage'] = (res) => {
|
|
35
|
-
if (res?.from === 'button' && res?.target?.dataset?.weda_share_info) {
|
|
36
|
-
return res?.target?.dataset?.weda_share_info;
|
|
37
|
-
}
|
|
38
|
-
if (res?.from === 'menu' && pageAttributes?.appShareMessage) {
|
|
39
|
-
let { enable, pageId, params, imageUrl, title } = pageAttributes.appShareMessage;
|
|
40
|
-
if (enable) {
|
|
41
|
-
pageId = pageId ? pageId.replace(/^(\.)?\//, '') : pageId;
|
|
42
|
-
let realPath = `/pages/${pageId}/index` + (params ? '?' + params.map(pair => pair.key + '=' + pair.value).join('&') : '');
|
|
43
|
-
return {
|
|
44
|
-
path: realPath,
|
|
45
|
-
imageUrl,
|
|
46
|
-
title
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
try {
|
|
51
|
-
return lifecycle?.['onShareAppMessage']?.() || {};
|
|
52
|
-
} catch (error) {
|
|
53
|
-
console.log(error);
|
|
54
|
-
return {};
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return result;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return Component({
|
|
61
|
-
_componentType: 'page',
|
|
62
|
-
data: createInitData(widgetProps, dataBinds),
|
|
63
|
-
lifetimes: {
|
|
64
|
-
attached() {
|
|
65
|
-
const $page = this.getWeAppInst()
|
|
66
|
-
// createWidgets 从上面移到这里是为了 i18n 切换语言的时候页面能生效
|
|
67
|
-
$page.widgets = {};
|
|
68
|
-
const { rootWidget, widgets } = createWidgets(widgetProps, dataBinds, $page.widgets, context);
|
|
69
|
-
this._rootWidget = rootWidget;
|
|
70
|
-
this._widgets = widgets;
|
|
71
|
-
this._pageActive = true;
|
|
72
|
-
this.__handlerAttached__ = (e) => {
|
|
73
|
-
if (!$page.componentMethods) {
|
|
74
|
-
$page.componentMethods = {};
|
|
75
|
-
}
|
|
76
|
-
const [id, index = 0] = e.target.id.split('-');
|
|
77
|
-
if (!$page.componentMethods[id]) {
|
|
78
|
-
$page.componentMethods[id] = [];
|
|
79
|
-
}
|
|
80
|
-
$page.componentMethods[id][index] = e.detail.methods;
|
|
81
|
-
};
|
|
82
|
-
this.__handlerDetached__ = (e) => {
|
|
83
|
-
const [id, index = 0] = e.target.id.split('-');
|
|
84
|
-
if ($page.componentMethods) {
|
|
85
|
-
const components = $page.componentMethods[id];
|
|
86
|
-
if (components) {
|
|
87
|
-
components[index] = undefined;
|
|
88
|
-
if (components.filter(com => com !== undefined).length === 0) {
|
|
89
|
-
delete $page.componentMethods[id];
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
this._disposers = this.initMergeRenderer(widgets);
|
|
95
|
-
},
|
|
96
|
-
detached() {
|
|
97
|
-
disposeWidget(this._rootWidget);
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
pageLifetimes: {
|
|
101
|
-
// 组件所在页面的生命周期函数,定义下给运营平台上报用
|
|
102
|
-
show: function () {
|
|
103
|
-
},
|
|
104
|
-
hide: function () {
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
methods: {
|
|
108
|
-
_pageActive: true,
|
|
109
|
-
/** page lifecycles **/
|
|
110
|
-
...extractLifecyles(),
|
|
111
|
-
...evtHandlers,
|
|
112
|
-
...mergeRenderer,
|
|
113
|
-
onLoad(options) {
|
|
114
|
-
const $page = this.getWeAppInst()
|
|
115
|
-
|
|
116
|
-
app.__internal__.activePage = $page;
|
|
117
|
-
setConfig({ currentPageId: $page.uuid });
|
|
118
|
-
this._pageActive = true;
|
|
119
|
-
|
|
120
|
-
let query = decodePageQuery(options || {});
|
|
121
|
-
EXTRA_API.setParams($page.uuid, query);
|
|
122
|
-
createStateDataSourceVar($page.uuid, generateParamsParser({ app, $page }));
|
|
123
|
-
|
|
124
|
-
const hook = lifecycle.onLoad || lifecycle.onPageLoad;
|
|
125
|
-
hook && hook.call(this, query);
|
|
126
|
-
},
|
|
127
|
-
onUnload() {
|
|
128
|
-
const $page = this.getWeAppInst()
|
|
129
|
-
this._disposers.forEach(dispose => dispose());
|
|
130
|
-
|
|
131
|
-
const hook = lifecycle.onUnload || lifecycle.onPageUnload;
|
|
132
|
-
hook && hook.call(this);
|
|
133
|
-
},
|
|
134
|
-
async onShow() {
|
|
135
|
-
const $page = this.getWeAppInst()
|
|
136
|
-
app.__internal__.activePage = $page;
|
|
137
|
-
setConfig({ currentPageId: $page.uuid });
|
|
138
|
-
$page.widgets = this._widgets;
|
|
139
|
-
this._pageActive = true;
|
|
140
|
-
|
|
141
|
-
const hook = lifecycle.onShow || lifecycle.onPageShow;
|
|
142
|
-
hook && hook.call(this);
|
|
143
|
-
|
|
144
|
-
// 权限检查
|
|
145
|
-
if (await checkAuth(app, app.id, $page)) {
|
|
146
|
-
this.setData({
|
|
147
|
-
weDaHasLogin: true,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
onHide() {
|
|
152
|
-
const $page = this.getWeAppInst()
|
|
153
|
-
const hook = lifecycle.onHide || lifecycle.onPageHide;
|
|
154
|
-
hook && hook.call(this);
|
|
155
|
-
this._pageActive = false;
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
getWeAppInst() {
|
|
159
|
-
if (!this.$WEAPPS_PAGE) {
|
|
160
|
-
$page.state = observable(pageState);
|
|
161
|
-
let dataset = createDataset($page.uuid);
|
|
162
|
-
$page.dataset = dataset;
|
|
163
|
-
$page.state.dataset = dataset;
|
|
164
|
-
$page.computed = createComputed(pageComputed);
|
|
165
|
-
$page.setState = (userSetState) => {
|
|
166
|
-
Object.keys(userSetState).forEach((keyPath) => {
|
|
167
|
-
app.utils.set($page.dataset.state, keyPath, userSetState[keyPath]);
|
|
168
|
-
});
|
|
169
|
-
};
|
|
170
|
-
$page.invokeComponentMethod = ({ component, method, params }) => {
|
|
171
|
-
const components = lodashGet($page.componentMethods, component);
|
|
172
|
-
let componentInstance = undefined
|
|
173
|
-
if (Array.isArray(components)) {
|
|
174
|
-
if(components.length > 1){
|
|
175
|
-
throw new Error('调用方法失败:id为'+component+'的组件拥有多个实例')
|
|
176
|
-
}
|
|
177
|
-
componentInstance = components[0]
|
|
178
|
-
// components.forEach(component => {
|
|
179
|
-
// component[method](params);
|
|
180
|
-
// })
|
|
181
|
-
} else {
|
|
182
|
-
componentInstance = components
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if(!componentInstance?.[method] || typeof componentInstance[method]!= 'function') {
|
|
186
|
-
throw new Error('调用方法失败:未找到id为'+component+'下的方法'+method)
|
|
187
|
-
}
|
|
188
|
-
return componentInstance[method](params);
|
|
189
|
-
};
|
|
190
|
-
this.$WEAPPS_PAGE = $page;
|
|
191
|
-
}
|
|
192
|
-
return this.$WEAPPS_PAGE
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function decodePageQuery(query) {
|
|
199
|
-
return Object.keys(query)
|
|
200
|
-
.reduce((decoded, key) => {
|
|
201
|
-
decoded[key] = decodeURIComponent(query[key]);
|
|
202
|
-
return decoded;
|
|
203
|
-
}, {});
|
|
204
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { urlJoinParams } from './url'
|
|
2
|
-
import { promisifyAll } from 'miniprogram-api-promise'
|
|
3
|
-
|
|
4
|
-
function createNavigatorFn(fnName) {
|
|
5
|
-
return function ({ pageId, packageName, params, mode='', events, success, fail, complete }) {
|
|
6
|
-
let url;
|
|
7
|
-
if(mode == 'plugin'){
|
|
8
|
-
url = `plugin://${packageName}/${pageId}`
|
|
9
|
-
} else if(mode ==='web'){
|
|
10
|
-
console.warn(`${fnName} url can only be used in h5 build`);
|
|
11
|
-
return;
|
|
12
|
-
} else {
|
|
13
|
-
pageId = pageId ? pageId.replace(/^(\.)?\//,'') : pageId;
|
|
14
|
-
url = packageName
|
|
15
|
-
? `/${packageName}/pages/${pageId}/index`
|
|
16
|
-
: `/pages/${pageId}/index`
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (fnName === 'navigateTo') {
|
|
20
|
-
navigateToFn(urlJoinParams(url, params), { events, success, fail, complete});
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
wx[fnName]({
|
|
25
|
-
url: urlJoinParams(url, params),
|
|
26
|
-
events,
|
|
27
|
-
success,
|
|
28
|
-
fail,
|
|
29
|
-
complete
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 页面堆栈10以内使用wx.navigateTo,超过10则使用wx.redirectTo
|
|
36
|
-
* @param url
|
|
37
|
-
* @param param1
|
|
38
|
-
* @returns
|
|
39
|
-
*/
|
|
40
|
-
function navigateToFn(url, { events, success, fail, complete}) {
|
|
41
|
-
const pages = getCurrentPages();
|
|
42
|
-
if(pages && pages.length >= 10) {
|
|
43
|
-
wx.redirectTo({
|
|
44
|
-
url,
|
|
45
|
-
success,
|
|
46
|
-
fail,
|
|
47
|
-
complete
|
|
48
|
-
});
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
wx.navigateTo({
|
|
53
|
-
url,
|
|
54
|
-
// @types/weixin-app@2.9.3没有events的定义,但实际上官方文档有:https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateTo.html
|
|
55
|
-
// @ts-ignore
|
|
56
|
-
events,
|
|
57
|
-
success,
|
|
58
|
-
fail,
|
|
59
|
-
complete
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const navigateTo = createNavigatorFn('navigateTo')
|
|
64
|
-
const reLaunch = createNavigatorFn('reLaunch')
|
|
65
|
-
const redirectTo = createNavigatorFn('redirectTo')
|
|
66
|
-
|
|
67
|
-
export const wxp = {}
|
|
68
|
-
promisifyAll(wx, wxp)
|
|
69
|
-
|
|
70
|
-
export default {
|
|
71
|
-
...wxp,
|
|
72
|
-
navigateTo,
|
|
73
|
-
reLaunch,
|
|
74
|
-
redirectTo,
|
|
75
|
-
auth: undefined
|
|
76
|
-
}
|
|
@@ -1,381 +0,0 @@
|
|
|
1
|
-
import { observable, autorun, untracked } from 'mobx'
|
|
2
|
-
import { styleToCss } from './style'
|
|
3
|
-
import { getDeep } from './util'
|
|
4
|
-
import { compLowcodes, create$comp } from './weapp-component'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* convert widget prop to data for wxml
|
|
8
|
-
* @param {*} props
|
|
9
|
-
*/
|
|
10
|
-
function resolveWidgetProp(props) {
|
|
11
|
-
let { classList = [] } = props
|
|
12
|
-
const data = {}
|
|
13
|
-
Object.keys(props).forEach(key => {
|
|
14
|
-
if (props[key] instanceof Function || props[key] === undefined) {
|
|
15
|
-
return
|
|
16
|
-
}
|
|
17
|
-
data[key] = props[key]
|
|
18
|
-
})
|
|
19
|
-
data.style = styleToCss(props.style)
|
|
20
|
-
data.className = classList.join ? classList.join(' ') : classList
|
|
21
|
-
const extraProps = ['classList', '_forItems', '_disposers', 'children', 'parent', '_parentId', 'id', '_order', 'widgetType', '$comp']
|
|
22
|
-
extraProps.map(prop => {
|
|
23
|
-
delete data[prop]
|
|
24
|
-
})
|
|
25
|
-
return data
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// widget prop -> wxml data
|
|
29
|
-
export function resolveWidgetData(props) {
|
|
30
|
-
if (!Array.isArray(props)) {
|
|
31
|
-
return resolveWidgetProp(props)
|
|
32
|
-
}
|
|
33
|
-
return props.map(resolveWidgetData)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
export function createWidgets(widgetProps, dataBinds, widgetHolder, context, ownerMpInst) {
|
|
38
|
-
const rootNode = createWidgetDataTree(widgetProps, dataBinds)
|
|
39
|
-
return createSubWidgetTree(rootNode, widgetProps, dataBinds, ownerMpInst, widgetHolder, undefined, undefined, undefined, undefined, undefined, context)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @param ownerMpInst The MP page or component instance the widgets belongs to
|
|
44
|
-
* @param ownerForWidgetHolder null for the virtual root node(first run)
|
|
45
|
-
* @param curForNode a component node or a virtual root tree node
|
|
46
|
-
* @returns {widgets: {id1:[], id2}, rootWidget: {children: [], _disposers: [], ...otherProps}}
|
|
47
|
-
*/
|
|
48
|
-
function createSubWidgetTree(curForNode, widgetProps, dataBinds, ownerMpInst, widgetHolder = {},
|
|
49
|
-
index = 0, forItems = {}, ownerForWidgetHolder = null,
|
|
50
|
-
failedBinds = [], defaultParent = { children: observable([]), _disposers: [] }, context = {}) {
|
|
51
|
-
const indexPostfix = (forItems.lists || []).slice().reverse().map(list => idSeparator + list.currentIndex).join('')
|
|
52
|
-
|
|
53
|
-
// traverse down the tree to set up all widgets
|
|
54
|
-
dfsTree(curForNode, (node) => {
|
|
55
|
-
const parentForWidgetArr = ownerForWidgetHolder && ownerForWidgetHolder[node.id] || []
|
|
56
|
-
const existedWidget = index < parentForWidgetArr.length ? parentForWidgetArr[index] : null // try to reuse previous node when rerun for
|
|
57
|
-
|
|
58
|
-
if (node.forCount === curForNode.forCount) { // Leaf node
|
|
59
|
-
let w = existedWidget
|
|
60
|
-
if (!existedWidget) {
|
|
61
|
-
const parentNode = node.parent
|
|
62
|
-
let parentWidget = null
|
|
63
|
-
if (parentNode) {
|
|
64
|
-
parentWidget = widgetHolder[parentNode.id] || ownerForWidgetHolder[parentNode.id]
|
|
65
|
-
}
|
|
66
|
-
w = createAWidget(widgetProps[node.id], node.id + indexPostfix, parentWidget, ownerMpInst)
|
|
67
|
-
if (!parentWidget) {
|
|
68
|
-
defaultParent.children.push(w)
|
|
69
|
-
}
|
|
70
|
-
parentForWidgetArr.push(w)
|
|
71
|
-
} else {
|
|
72
|
-
disposeWidget(existedWidget, true)
|
|
73
|
-
}
|
|
74
|
-
setUpWidateDataBinds(w, dataBinds[node.id], forItems, failedBinds, context)
|
|
75
|
-
widgetHolder[node.id] = w
|
|
76
|
-
} else if (!existedWidget) {
|
|
77
|
-
const len = parentForWidgetArr.push(observable([]))
|
|
78
|
-
widgetHolder[node.id] = parentForWidgetArr[len - 1]
|
|
79
|
-
} else {
|
|
80
|
-
// Reuse existed for widget array
|
|
81
|
-
widgetHolder[node.id] = existedWidget
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
// run for of next level
|
|
86
|
-
dfsTree(curForNode, (node) => {
|
|
87
|
-
if (node.forCount === curForNode.forCount + 1 && dataBinds[node.id] && dataBinds[node.id]._waFor) {
|
|
88
|
-
// find the node bound with next level for
|
|
89
|
-
const parent = node.parent ? widgetHolder[node.parent.id] : defaultParent
|
|
90
|
-
const dispose = runFor(node, widgetProps, dataBinds, ownerMpInst, forItems, widgetHolder, failedBinds, parent, context)
|
|
91
|
-
parent._disposers.push(dispose) // Add the for bind dispose to the parent node of forNode
|
|
92
|
-
}
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
// Retry failed databinds
|
|
96
|
-
const len = failedBinds.length
|
|
97
|
-
for (let i = 0; i < len; i++) {
|
|
98
|
-
const setUpDataBind = failedBinds.shift()
|
|
99
|
-
setUpDataBind()
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return { widgets: widgetHolder, rootWidget: widgetHolder[curForNode.id] || defaultParent }
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
*
|
|
107
|
-
* @param {*} curForNode
|
|
108
|
-
* @param {*} forItems
|
|
109
|
-
* @param {*} parentForWidgets
|
|
110
|
-
* @param {*} parentWidget
|
|
111
|
-
* @returns top level widgets or for dispose
|
|
112
|
-
*/
|
|
113
|
-
function runFor(curForNode, widgetProps, dataBinds, ownerMpInst, forItems, ownerForWidgetHolder, failedBinds, defaultParent, context) {
|
|
114
|
-
const nodeId = curForNode.id
|
|
115
|
-
const dispose = autorun(() => {
|
|
116
|
-
let forList = []
|
|
117
|
-
try {
|
|
118
|
-
forList = dataBinds[nodeId]._waFor(forItems.lists, forItems.itemsById, undefined, context)
|
|
119
|
-
if (!Array.isArray(forList)) {
|
|
120
|
-
forList = []
|
|
121
|
-
}
|
|
122
|
-
} catch (e) {
|
|
123
|
-
forList = []
|
|
124
|
-
console.warn('For binding error', e)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Track list change (e.g. push)
|
|
128
|
-
forList.forEach(e => { })
|
|
129
|
-
|
|
130
|
-
untracked(() => {
|
|
131
|
-
// dispose widgets before reused instead
|
|
132
|
-
// disposeWidgets(parentForWidgets[curForNode.id])
|
|
133
|
-
|
|
134
|
-
// clean extra widgets of previous for run
|
|
135
|
-
dfsTree(curForNode, (node) => {
|
|
136
|
-
const arr = ownerForWidgetHolder[node.id]
|
|
137
|
-
const extraWidgets = arr.splice(forList.length, arr.length)
|
|
138
|
-
//console.log('@@ delete widgets', node.id, extraWidgets)
|
|
139
|
-
|
|
140
|
-
if (node.id === curForNode.id) { // clean the root widget.children only(recursive)
|
|
141
|
-
extraWidgets.map(w => {
|
|
142
|
-
disposeWidget(w)
|
|
143
|
-
const { children } = w.parent || defaultParent
|
|
144
|
-
children.remove(w)
|
|
145
|
-
// w.parent = null
|
|
146
|
-
})
|
|
147
|
-
}
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
forList.forEach((item, index) => {
|
|
151
|
-
let { lists = [], itemsById = {}, } = forItems
|
|
152
|
-
const _forItems = {
|
|
153
|
-
lists: [{ currentItem: item, currentIndex: index }, ...lists],
|
|
154
|
-
itemsById: { ...itemsById, [nodeId]: item },
|
|
155
|
-
}
|
|
156
|
-
const { rootWidget } = createSubWidgetTree(curForNode, widgetProps, dataBinds, ownerMpInst, {}, index, _forItems, ownerForWidgetHolder, failedBinds, defaultParent, context)
|
|
157
|
-
rootWidget._forItems = _forItems
|
|
158
|
-
})
|
|
159
|
-
})
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
return dispose
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function createAWidget(props, id, parent, ownerMpInst) {
|
|
166
|
-
|
|
167
|
-
const w = observable(props)
|
|
168
|
-
|
|
169
|
-
// Builtin props
|
|
170
|
-
Object.defineProperty(w, 'id', { value: id })
|
|
171
|
-
const { widgetType } = w
|
|
172
|
-
delete w.widgetType
|
|
173
|
-
Object.defineProperty(w, 'widgetType', { value: widgetType })
|
|
174
|
-
|
|
175
|
-
//w._disposers = []
|
|
176
|
-
//w.children = []
|
|
177
|
-
Object.defineProperty(w, 'children', { value: observable([]) })
|
|
178
|
-
Object.defineProperty(w, '_disposers', { value: observable([]) })
|
|
179
|
-
if (parent) {
|
|
180
|
-
//w.parent = parent
|
|
181
|
-
Object.defineProperty(w, 'parent', { value: parent })
|
|
182
|
-
parent.children.push(w)
|
|
183
|
-
}
|
|
184
|
-
delete w._parentId
|
|
185
|
-
|
|
186
|
-
Object.defineProperty(w, '$comp', { value: create$comp(w) })
|
|
187
|
-
mountBuiltinWigetsAPI(w, ownerMpInst)
|
|
188
|
-
return w
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function setUpWidateDataBinds(w, dataBinds, forItems, failedBinds, context) {
|
|
192
|
-
Object.keys(dataBinds || {}).map(prop => {
|
|
193
|
-
if (prop === '_waFor') { return }
|
|
194
|
-
const setUpDataBind = () => {
|
|
195
|
-
let firstRunError = null
|
|
196
|
-
const dispose = autorun(() => {
|
|
197
|
-
try {
|
|
198
|
-
// Computed data bind in the next tick since data bind may read widgets data
|
|
199
|
-
w[prop] = dataBinds[prop](forItems.lists, forItems.itemsById, undefined, context)
|
|
200
|
-
} catch (e) {
|
|
201
|
-
if(prop === '_waIf'){
|
|
202
|
-
w[prop] = false
|
|
203
|
-
console.warn(`Error computing data bind ${w.id}.${prop}`, e)
|
|
204
|
-
}else {
|
|
205
|
-
// 吞错误,因为部分异步的属性刚开始没有,
|
|
206
|
-
// 要求用户自己容错又要求太高,因此直接吞掉错误,只打印,不阻塞
|
|
207
|
-
// firstRunError = e
|
|
208
|
-
console.error(`Error computing data bind ${w.id}.${prop}`, e)
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
})
|
|
212
|
-
if (firstRunError) {
|
|
213
|
-
dispose()
|
|
214
|
-
failedBinds.push(setUpDataBind)
|
|
215
|
-
} else {
|
|
216
|
-
w._disposers.push(dispose)
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
setUpDataBind()
|
|
220
|
-
})
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export function findForItemsOfWidget(widget) {
|
|
224
|
-
const forItems = widget._forItems
|
|
225
|
-
if (forItems) return forItems
|
|
226
|
-
if (widget.parent) return findForItemsOfWidget(widget.parent)
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const idSeparator = '-'
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
*
|
|
233
|
-
* @param {*} owner Mp page or component instance
|
|
234
|
-
* @param {*} comp Mp component instance or event.currentTarget, the component to convert
|
|
235
|
-
*/
|
|
236
|
-
export function mpCompToWidget(owner, comp) {
|
|
237
|
-
const { widgets } = owner.getWeAppInst()
|
|
238
|
-
return getDeep(widgets, comp.id, idSeparator)
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Add parent, children to widget
|
|
243
|
-
*/
|
|
244
|
-
function createWidgetDataTree(widgets, dataBinds) {
|
|
245
|
-
const virtualRoot = { children: [], forCount: 0 }
|
|
246
|
-
const nodes = Object.keys(widgets).reduce((result, id) => {
|
|
247
|
-
const w = widgets[id]
|
|
248
|
-
result[id] = { id, value: w, _order: w._order, children: [], parent: null, forCount: 0 }
|
|
249
|
-
delete w._order
|
|
250
|
-
return result
|
|
251
|
-
}, {})
|
|
252
|
-
|
|
253
|
-
// Create widgets tree API
|
|
254
|
-
Object.keys(nodes).map(id => {
|
|
255
|
-
const curNode = nodes[id]
|
|
256
|
-
const parent = nodes[widgets[id]._parentId]
|
|
257
|
-
//delete widgets[id]._parentId
|
|
258
|
-
if (!parent) {
|
|
259
|
-
virtualRoot.children.push(curNode)
|
|
260
|
-
return
|
|
261
|
-
}
|
|
262
|
-
curNode.parent = parent
|
|
263
|
-
parent.children.push(curNode)
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
// Sort children
|
|
267
|
-
Object.keys(nodes).map(id => {
|
|
268
|
-
nodes[id].children.sort((a, b) => a._order - b._order)
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
virtualRoot.children.map(addForCount)
|
|
272
|
-
|
|
273
|
-
// dfs, add forCount
|
|
274
|
-
function addForCount(node) {
|
|
275
|
-
if (node.parent) {
|
|
276
|
-
node.forCount = node.parent.forCount
|
|
277
|
-
}
|
|
278
|
-
if (dataBinds[node.id] && dataBinds[node.id]._waFor) {
|
|
279
|
-
node.forCount++
|
|
280
|
-
}
|
|
281
|
-
node.children.map(addForCount)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return virtualRoot
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function dfsTree(node, fn, parent) {
|
|
288
|
-
node.value && fn(node, parent)
|
|
289
|
-
node.children.map(e => dfsTree(e, fn, node.value ? node : null))
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// dispose autorun, widget can be the virtual root widget
|
|
293
|
-
export function disposeWidget(widget, noRecursive) {
|
|
294
|
-
const disposers = widget._disposers
|
|
295
|
-
disposers.map(dispose => dispose())
|
|
296
|
-
disposers.splice(0, disposers.length)
|
|
297
|
-
!noRecursive && widget.children.forEach(w => disposeWidget(w))
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
export function createInitData(widgets, dataBinds, keyPrefix = '') {
|
|
301
|
-
return Object.keys(widgets).reduce((result, id) => {
|
|
302
|
-
if (!isWidgetInFor(id, widgets, dataBinds)) {
|
|
303
|
-
result[keyPrefix + id] = resolveWidgetData(widgets[id])
|
|
304
|
-
}
|
|
305
|
-
return result
|
|
306
|
-
}, {})
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function isWidgetInFor(id, widgets, dataBinds) {
|
|
310
|
-
let curNode = widgets[id]
|
|
311
|
-
let nodeId = id
|
|
312
|
-
while (curNode) {
|
|
313
|
-
if (dataBinds[nodeId] && dataBinds[nodeId]._waFor) {
|
|
314
|
-
return true
|
|
315
|
-
}
|
|
316
|
-
nodeId = curNode._parentId
|
|
317
|
-
curNode = widgets[nodeId]
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
function mountBuiltinWigetsAPI(widget, owner) {
|
|
322
|
-
// #1 builtin APIs
|
|
323
|
-
widget.findWidgets = function (filter, includeInvisibleDescendants) {
|
|
324
|
-
let { children = [] } = this
|
|
325
|
-
if (!includeInvisibleDescendants) { // include visible widgets only by default
|
|
326
|
-
children = children.filter(e => e._waIf !== false)
|
|
327
|
-
}
|
|
328
|
-
const matched = []
|
|
329
|
-
children.forEach(w => {
|
|
330
|
-
if (filter(w)) {
|
|
331
|
-
matched.push(w)
|
|
332
|
-
}
|
|
333
|
-
matched.push(...w.findWidgets(filter, includeInvisibleDescendants))
|
|
334
|
-
})
|
|
335
|
-
return matched
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
widget.getWidgetsByType = function (type, includeInvisibleDescendants) {
|
|
339
|
-
return this.findWidgets(w => w.widgetType === type, includeInvisibleDescendants)
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* Similar to selectOwnerComponent of WX MP: https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html
|
|
344
|
-
*/
|
|
345
|
-
widget.getOwnerWidget = function () {
|
|
346
|
-
return owner && owner.getWeAppInst().node
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Will be overwritten by composited component
|
|
350
|
-
widget.getDom = function (fields) {
|
|
351
|
-
return new Promise((resolve, reject) => {
|
|
352
|
-
const query = (owner || wx).createSelectorQuery()
|
|
353
|
-
query.select('#' + this.id).fields(fields, res => {
|
|
354
|
-
resolve(res)
|
|
355
|
-
}).exec()
|
|
356
|
-
})
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
widget.getConfig = () => ({})
|
|
360
|
-
|
|
361
|
-
const lowcode = compLowcodes[widget.widgetType]
|
|
362
|
-
if (lowcode) {
|
|
363
|
-
const { index = {}, config } = lowcode
|
|
364
|
-
|
|
365
|
-
widget.getConfig = () => config
|
|
366
|
-
|
|
367
|
-
// #2 User defined APIs
|
|
368
|
-
const { publicMethods = {} } = index
|
|
369
|
-
Object.keys(publicMethods).map(name => {
|
|
370
|
-
const method = publicMethods[name]
|
|
371
|
-
if (method instanceof Function) {
|
|
372
|
-
Object.defineProperty(widget, name, { value: method.bind(widget.$comp) })
|
|
373
|
-
Object.defineProperty(widget.$comp, name, { value: method })
|
|
374
|
-
} else {
|
|
375
|
-
console.error(`Component(${widget.widgetType}) method(${name}) is not a function.`)
|
|
376
|
-
}
|
|
377
|
-
})
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
widget._methods = {}
|
|
381
|
-
}
|