@cloudbase/lowcode-builder 1.0.39 → 1.1.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.
@@ -315,7 +315,7 @@ async function generatePkg(weapp, appRoot, ctx, pageConfigs) {
315
315
  pageUUID: rootPath ? `${rootPath}/${page.id}` : page.id,
316
316
  pageName: page.id,
317
317
  pageSource: page.data.src || '',
318
- eventHanlders: (0, util_2.createEventHanlders)(page.componentInstances, 'this', ctx),
318
+ eventHanlders: (0, util_2.createEventHanlders)(page.componentInstances, 'this', ctx, page),
319
319
  dataBinds: (0, util_2.createDataBinds)(page.componentInstances, ctx),
320
320
  pageAttributes: {
321
321
  ...(((_a = page.data) === null || _a === void 0 ? void 0 : _a.appShareMessage) ? { appShareMessage: page.data.appShareMessage.value } : {}),
@@ -1,4 +1,4 @@
1
- import { IDynamicValue, IWeAppComponentInstance, ICompositedComponent } from '@cloudbase/lowcode-generator/lib/weapps-core';
1
+ import { IDynamicValue, IWeAppComponentInstance, ICompositedComponent, IWeAppPage } from '@cloudbase/lowcode-generator/lib/weapps-core';
2
2
  import { IBuildContext } from './BuildContext';
3
3
  export declare function extractWidgetProps(props: Required<IWeAppComponentInstance>['xProps'], compInfo: ICompositedComponent): any;
4
4
  export declare function generatedDynamicData(data: {
@@ -7,13 +7,12 @@ export declare function generatedDynamicData(data: {
7
7
  staticProps: {};
8
8
  boundProps: {};
9
9
  };
10
- export declare function generateDataBind(bind: IDynamicValue): string;
11
10
  export declare function createWidgetProps(widgets: {
12
11
  [key: string]: IWeAppComponentInstance;
13
12
  }, ctx: IBuildContext): {};
14
13
  export declare function createEventHanlders(widgets: {
15
14
  [key: string]: IWeAppComponentInstance;
16
- }, componentApi: string, ctx: IBuildContext): {};
15
+ }, componentApi: string, ctx: IBuildContext, page?: IWeAppPage): {};
17
16
  export declare function createDataBinds(widgets: {
18
17
  [key: string]: IWeAppComponentInstance;
19
18
  }, ctx: IBuildContext): {};
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createDataBinds = exports.createEventHanlders = exports.createWidgetProps = exports.generateDataBind = exports.generatedDynamicData = exports.extractWidgetProps = void 0;
3
+ exports.createDataBinds = exports.createEventHanlders = exports.createWidgetProps = exports.generatedDynamicData = exports.extractWidgetProps = void 0;
4
4
  const weapps_core_1 = require("@cloudbase/lowcode-generator/lib/weapps-core");
5
+ const lowcode_generator_1 = require("@cloudbase/lowcode-generator");
5
6
  const weapp_1 = require("@cloudbase/lowcode-generator/lib/generator/util/weapp");
6
7
  const wxml_1 = require("./wxml");
7
8
  const mp_1 = require("@cloudbase/lowcode-generator/lib/generator/config/mp");
@@ -47,20 +48,27 @@ function generatedDynamicData(data, compInfo) {
47
48
  }
48
49
  }
49
50
  else {
50
- boundProps[key] = generateDataBind(data[key]);
51
+ setDataBind(boundProps, key, data[key]);
51
52
  }
52
53
  }
53
54
  return { staticProps, boundProps };
54
55
  }
55
56
  exports.generatedDynamicData = generatedDynamicData;
56
57
  // For JS
57
- function generateDataBind(bind) {
58
+ function generateDataBindMeta(bind) {
58
59
  let expr = '';
60
+ let imports = 'const $for = forItems; const $index=lists?.[0]?.currentIndex;'; // 基础 alias
59
61
  const { type, value } = bind;
60
62
  if (type === weapps_core_1.PropBindType.forItem) {
61
- expr = `forItems.${value}`;
63
+ expr = `$for.${value}`;
62
64
  }
63
65
  else if (type === weapps_core_1.PropBindType.expression) {
66
+ try {
67
+ imports += (0, lowcode_generator_1.generateExpressionAlias)(value);
68
+ }
69
+ catch (e) {
70
+ console.error('parse expression error', value, e);
71
+ }
64
72
  expr = value;
65
73
  }
66
74
  else if (type === weapps_core_1.PropBindType.prop) {
@@ -98,9 +106,8 @@ function generateDataBind(bind) {
98
106
  }
99
107
  }
100
108
  }
101
- return expr;
109
+ return { imports, expression: expr };
102
110
  }
103
- exports.generateDataBind = generateDataBind;
104
111
  function createWidgetProps(widgets, ctx) {
105
112
  const widgetProps = {};
106
113
  (0, weapp_1.walkThroughWidgets)(widgets, (id, widget, parentId) => {
@@ -130,8 +137,9 @@ function createWidgetProps(widgets, ctx) {
130
137
  return widgetProps;
131
138
  }
132
139
  exports.createWidgetProps = createWidgetProps;
133
- function createEventHanlders(widgets, componentApi, ctx) {
134
- const eventHanlders = {};
140
+ function createEventHanlders(widgets, componentApi, ctx, page) {
141
+ let eventHandlers = {};
142
+ const { listeners: pageListeners = [], id: pageId = '' } = page || {};
135
143
  (0, weapp_1.walkThroughWidgets)(widgets, (id, widget, parentId) => {
136
144
  var _a, _b, _c;
137
145
  const { xComponent } = widget;
@@ -168,43 +176,15 @@ function createEventHanlders(widgets, componentApi, ctx) {
168
176
  });
169
177
  });
170
178
  }
171
- listeners.forEach((l) => {
172
- var _a, _b, _c;
173
- const handlerName = (0, wxml_1.getMpEventHanlderName)(id, l.trigger, l);
174
- eventHanlders[handlerName] = eventHanlders[handlerName] || [];
175
- const params = generatedDynamicData(l.data);
176
- let handler = l.handler ? l.handler.name : l.jsCode;
177
- switch (l.type) {
178
- case weapps_core_1.ActionType.Platform: {
179
- handler = `function({data}){ return app.${(_a = l.handler) === null || _a === void 0 ? void 0 : _a.name}(data)}`;
180
- break;
181
- }
182
- case weapps_core_1.ActionType.DataSource: {
183
- handler = `function({data}){ return app.cloud.callDataSource(data)}`;
184
- break;
185
- }
186
- case weapps_core_1.ActionType.PropEvent: {
187
- handler = `function({event, data = {}}){ return ${componentApi}.props.events.${(_b = l.handler) === null || _b === void 0 ? void 0 : _b.name}({...event.detail, ...data}) }`;
188
- break;
189
- }
190
- }
191
- eventHanlders[handlerName].push({
192
- key: l.key || '',
193
- handler: handler,
194
- handlerModule: (_c = l.handler) === null || _c === void 0 ? void 0 : _c.moduleName,
195
- data: params.staticProps,
196
- boundData: params.boundProps,
197
- type: l.type,
198
- });
199
- });
179
+ eventHandlers = Object.assign(eventHandlers, getListenersHandlers(listeners, id, componentApi));
200
180
  // 如果是数据容器,则生成一个onDataChange事件处理
201
181
  if ((_c = compProto === null || compProto === void 0 ? void 0 : compProto.compConfig) === null || _c === void 0 ? void 0 : _c.isDataContainer) {
202
182
  const customName = (0, wxml_1.getMpEventHanlderName)(id, 'onDataChange', {});
203
- eventHanlders[customName] = [
183
+ eventHandlers[customName] = [
204
184
  {
205
185
  key: '',
206
186
  handler: `({event})=>{
207
- app.utils.set(context, '${id}.data', event?.detail?.data);
187
+ event.currentTarget._scope.dataContext = {data: event?.detail?.data, state: event?.detail?.state}
208
188
  }`,
209
189
  handlerModule: weapps_core_1.ActionType.Platform,
210
190
  data: {},
@@ -213,9 +193,52 @@ function createEventHanlders(widgets, componentApi, ctx) {
213
193
  ];
214
194
  }
215
195
  });
216
- return eventHanlders;
196
+ // 增加页面事件节点 handlers
197
+ eventHandlers = Object.assign(eventHandlers, getListenersHandlers(pageListeners, pageId, componentApi));
198
+ return eventHandlers;
217
199
  }
218
200
  exports.createEventHanlders = createEventHanlders;
201
+ /**
202
+ * 根据 listeners 创建 handlers
203
+ * @param listeners {IEventListener[]}
204
+ * @param id {string}
205
+ * @param componentApi {string}
206
+ */
207
+ function getListenersHandlers(listeners, id, componentApi) {
208
+ if (!id)
209
+ return {};
210
+ const eventHandlers = {};
211
+ listeners.forEach((l) => {
212
+ var _a, _b, _c;
213
+ const handlerName = (0, wxml_1.getMpEventHanlderName)(id, l.trigger, l);
214
+ eventHandlers[handlerName] = eventHandlers[handlerName] || [];
215
+ const params = generatedDynamicData(l.data);
216
+ let handler = l.handler ? l.handler.name : l.jsCode;
217
+ switch (l.type) {
218
+ case weapps_core_1.ActionType.Platform: {
219
+ handler = `function({data}){ return app.${(_a = l.handler) === null || _a === void 0 ? void 0 : _a.name}(data)}`;
220
+ break;
221
+ }
222
+ case weapps_core_1.ActionType.DataSource: {
223
+ handler = `function({data}){ return app.cloud.callDataSource(data)}`;
224
+ break;
225
+ }
226
+ case weapps_core_1.ActionType.PropEvent: {
227
+ handler = `function({event, data = {}}){ return ${componentApi}.props.events.${(_b = l.handler) === null || _b === void 0 ? void 0 : _b.name}({...event.detail, ...data}) }`;
228
+ break;
229
+ }
230
+ }
231
+ eventHandlers[handlerName].push({
232
+ key: l.key || '',
233
+ handler: handler,
234
+ handlerModule: (_c = l.handler) === null || _c === void 0 ? void 0 : _c.moduleName,
235
+ data: params.staticProps,
236
+ boundData: params.boundProps,
237
+ type: l.type,
238
+ });
239
+ });
240
+ return eventHandlers;
241
+ }
219
242
  function createDataBinds(widgets, ctx) {
220
243
  const dataBinds = {};
221
244
  (0, weapp_1.walkThroughWidgets)(widgets, (id, widget, parentId) => {
@@ -242,10 +265,16 @@ function createDataBinds(widgets, ctx) {
242
265
  setDataBind(dataBinds[id], 'style', xProps.styleBind);
243
266
  const { classList, style } = dataBinds[id];
244
267
  if (classList) {
245
- dataBinds[id].classList = `concatClassList(${classList}, widgetProps.${id}.classList)`;
268
+ dataBinds[id].classList = {
269
+ ...classList,
270
+ expression: `concatClassList(${classList === null || classList === void 0 ? void 0 : classList.expression}, widgetProps.${id}.classList)`,
271
+ };
246
272
  }
247
273
  if (style) {
248
- dataBinds[id].style = `px2rpx({...widgetProps.${id}.style, ...(${style})})`;
274
+ dataBinds[id].style = {
275
+ ...style,
276
+ expression: `px2rpx({...widgetProps.${id}.style, ...(${style === null || style === void 0 ? void 0 : style.expression})})`,
277
+ };
249
278
  }
250
279
  if (Object.keys(dataBinds[id]).length === 0) {
251
280
  delete dataBinds[id];
@@ -255,10 +284,10 @@ function createDataBinds(widgets, ctx) {
255
284
  }
256
285
  exports.createDataBinds = createDataBinds;
257
286
  function setDataBind(target, prop, val) {
258
- if (val && val.type && val.type !== 'static') {
259
- const jsExpr = generateDataBind(val);
260
- if (jsExpr) {
261
- target[prop] = jsExpr;
287
+ if ((val === null || val === void 0 ? void 0 : val.type) && val.type !== 'static') {
288
+ const meta = generateDataBindMeta(val);
289
+ if (meta.expression) {
290
+ target[prop] = meta;
262
291
  }
263
292
  // Do not generate propBind since it's bound directly in wxml except for _waFor
264
293
  // const propsKeepPropBindInJs = ['_waFor', '_waIf']
@@ -159,7 +159,7 @@ function generateWxml(widgets, docTag, wxmlDataPrefix, ctx, usingComponents, com
159
159
  if (compSchema) {
160
160
  const fieldDef = compSchema[prop];
161
161
  if (!fieldDef && !isGlobalAttr(prop)) {
162
- console.log(error(`Prop(${prop}) does not exist on ${componentKey}. ${helpMsg}`));
162
+ // console.log(error(`Prop(${prop}) does not exist on ${componentKey}. ${helpMsg}`));
163
163
  continue;
164
164
  }
165
165
  if (fieldDef === null || fieldDef === void 0 ? void 0 : fieldDef.readOnly) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/lowcode-builder",
3
- "version": "1.0.39",
3
+ "version": "1.1.1",
4
4
  "description": "云开发 Tencent CloudBase Framework Low Code Plugin,将低码配置生成完整项目并一键部署云开发资源。",
5
5
  "author": "yhsunshining@gmail.com",
6
6
  "homepage": "https://github.com/TencentCloudBase/cloudbase-framework#readme",
@@ -38,8 +38,8 @@
38
38
  "url": "https://github.com/TencentCloudBase/cloudbase-framework/issues"
39
39
  },
40
40
  "dependencies": {
41
- "@cloudbase/cals": "^0.4.9",
42
- "@cloudbase/lowcode-generator": "^1.0.18",
41
+ "@cloudbase/cals": "^0.4.10",
42
+ "@cloudbase/lowcode-generator": "^1.1.1",
43
43
  "axios": "^0.21.0",
44
44
  "browserfs": "^1.4.3",
45
45
  "browserify-zlib": "^0.2.0",
@@ -461,7 +461,7 @@
461
461
  ></script>
462
462
  <script
463
463
  crossorigin
464
- src="https://qbase.cdn-go.cn/lcap/lcap-resource-cdngo/-/0.1.4/_files/static/weda-render/main.f25263146cb3af601abf.bundle.js"
464
+ src="https://qbase.cdn-go.cn/lcap/lcap-resource-cdngo/-/0.1.4/_files/static/weda-render/main.feb4a8869b806451d1da.bundle.js"
465
465
  ></script>
466
466
  </body>
467
467
  </html>
@@ -28,53 +28,70 @@ export function createComputed(funcs, bindContext = null) {
28
28
  return computed
29
29
  }
30
30
 
31
- export function createEventHandlers(evtListeners, context) {
32
- const evtHandlers = {}
31
+ export function generateDataContext(widget) {
32
+ const dataContext = {};
33
+ while (widget?._scope) {
34
+ if (widget._scope.dataContext && !isEmptyObj(widget._scope.dataContext)) {
35
+ dataContext[widget._scope.id] = widget._scope.dataContext;
36
+ }
37
+ widget = widget.parent;
38
+ }
39
+ return dataContext;
40
+ }
41
+
42
+ /**
43
+ *
44
+ * @param evtListeners
45
+ */
46
+ export function createEventHandlers(evtListeners) {
47
+ const evtHandlers = {};
33
48
  for (const name in evtListeners) {
34
- const listeners = evtListeners[name]
35
- evtHandlers[name] = function (event) {
36
- const self = this
37
- const owner = this.getWeAppInst()
38
- const target = getWidget(owner.widgets, event.target.id)
39
- const currentTarget = getWidget(owner.widgets, event.currentTarget.id)
40
- event.target = target
41
- event.currentTarget = currentTarget
42
- const [prefix = ''] = name.split('$')
49
+ const listeners = evtListeners[name];
50
+ evtHandlers[name] = function (event = {}) {
51
+ const self = this;
52
+ const owner = this.getWeAppInst();
53
+ const target = !!event?.target?.id ? getWidget(owner.widgets, event.target.id) : undefined;
54
+ const currentTarget = !!event?.currentTarget?.id ? getWidget(owner.widgets, event.currentTarget.id) : undefined;
55
+ event.target = target;
56
+ event.currentTarget = currentTarget;
57
+ const [prefix = ''] = name.split('$');
43
58
  // The page event handler
44
- const { lists = [], itemsById = {} } = findForItemsOfWidget(currentTarget) || {}
59
+ const { lists = [], itemsById = {} } = !!currentTarget && findForItemsOfWidget(currentTarget) || {}
60
+ const dataContext = generateDataContext(currentTarget)
61
+
45
62
  listeners.forEach(async l => {
46
- let { data = {}, boundData = {} } = l
47
- data = { ...data }
63
+ let { data = {}, boundData = {} } = l;
64
+ data = { ...data };
48
65
  try {
49
66
  for (const k in boundData) {
50
- set(data, k, boundData[k].call(owner, owner, lists, itemsById, event, context))
67
+ set(data, k, boundData[k].call(owner, owner, lists, itemsById, event, dataContext))
51
68
  }
52
- let res = await l.handler.call(owner, { event, lists, forItems: itemsById, data })
53
- let eventName = prefix && l.key ? `${prefix}$${l.key}_success` : ''
69
+ let res = await l.handler.call(owner, { event, lists, forItems: itemsById, data });
70
+ let eventName = prefix && l.key ? `${prefix}$${l.key}_success` : '';
54
71
  self[eventName] && self[eventName]({
55
72
  ...event,
56
73
  detail: res
57
- })
74
+ });
58
75
  } catch (e) {
59
- let eventName = l.key ? `${prefix}$${l.key}_fail` : ''
76
+ let eventName = l.key ? `${prefix}$${l.key}_fail` : '';
60
77
  if (self[eventName]) {
61
- console.error(`事件响应失败`, e)
78
+ console.error(`事件响应失败`, e);
62
79
  await self[eventName]({
63
80
  ...event,
64
81
  detail: e
65
- })
82
+ });
66
83
  } else {
67
84
  app.showToast({
68
85
  icon: 'error',
69
86
  title: `事件响应失败`
70
- })
71
- throw e
87
+ });
88
+ throw e;
72
89
  }
73
-
74
90
  }
75
91
  })
76
92
  }
77
93
  }
94
+
78
95
  return evtHandlers
79
96
  }
80
97
 
@@ -232,6 +249,7 @@ export function findLoginPage() {
232
249
  }
233
250
 
234
251
  let _AUTH_CONFIG_CACHE = null;
252
+
235
253
  export async function getAuthConfig() {
236
254
  const { app } = getApp();
237
255
  if (_AUTH_CONFIG_CACHE) {
@@ -261,6 +279,7 @@ export async function getAuthConfig() {
261
279
  }
262
280
 
263
281
  let _AUTH_CACHE_MAP = {}
282
+
264
283
  async function getAccessPermission(app, appId, pageId) {
265
284
  const cacheKey = `${appId}-${pageId}`
266
285
  if (_AUTH_CACHE_MAP[cacheKey] !== undefined) {
@@ -361,6 +380,7 @@ export function redirectToLogin(currentPage) {
361
380
 
362
381
  let loading = {};
363
382
  export let enumOptions = observable({});
383
+
364
384
  export function formatEnum(path, optionname) {
365
385
  // 判断是单选还是多选
366
386
  let isSingle = Array.isArray(path);
@@ -378,6 +398,7 @@ export function formatEnum(path, optionname) {
378
398
  // 对多选或者单选有不同处理
379
399
  return !isSingle ? value : multiTmp?.join(',');
380
400
  }
401
+
381
402
  function getEnumOptions(optionName) {
382
403
  if (enumOptions[optionName]) {
383
404
  return enumOptions[optionName];
@@ -390,6 +411,7 @@ function getEnumOptions(optionName) {
390
411
  }
391
412
  return '';
392
413
  }
414
+
393
415
  async function getGeneralOptions(optionName) {
394
416
  const { app } = getApp();
395
417
  return app.cloud.callWedaApi({
@@ -401,3 +423,26 @@ async function getGeneralOptions(optionName) {
401
423
  },
402
424
  });
403
425
  }
426
+
427
+ export function getMpEventHandlerName(widgetId, evtName, modifier = {}) {
428
+ // Only builtin events have will bubble
429
+ return `on${widgetId}$${evtName.replace(/\./g, '_')}${modifier.isCapturePhase ? '$cap' : ''}${
430
+ modifier.noPropagation ? '$cat' : ''
431
+ }`;
432
+ }
433
+
434
+ function isPlainObject(src) {
435
+ return Object.prototype.toString.call(src) === '[object Object]';
436
+ }
437
+
438
+ const isEmptyObj = (obj) => {
439
+ if (!isPlainObject(obj)) {
440
+ return false;
441
+ }
442
+ for (const i in obj) {
443
+ if (Object.prototype.hasOwnProperty.call(obj, i)) {
444
+ return false;
445
+ }
446
+ }
447
+ return true;
448
+ };
@@ -12,7 +12,7 @@ import { createInitData } from './widget';
12
12
  */
13
13
  export const compLowcodes = {}
14
14
 
15
- export function createComponent(key, behaviors, properties, events, handler, dataBinds, evtListeners, widgetProps, index, lifeCycle, stateFn, computedFuncs, config, libCommonRes, undefined, context) {
15
+ export function createComponent(key, behaviors, properties, events, handler, dataBinds, evtListeners, widgetProps, index, lifeCycle, stateFn, computedFuncs, config, libCommonRes, libCode) {
16
16
  const initData = createInitData(widgetProps, dataBinds, '');
17
17
  compLowcodes[key] = {
18
18
  index,
@@ -58,7 +58,7 @@ export function createComponent(key, behaviors, properties, events, handler, dat
58
58
 
59
59
  $comp.props.events = createPropEvents(events, this)
60
60
  $comp.widgets = {}
61
- const { widgets, rootWidget: virtualRootWidget } = createWidgets(widgetProps, dataBinds, $comp.widgets, context, this)
61
+ const { widgets, rootWidget: virtualRootWidget } = createWidgets(widgetProps, dataBinds, $comp.widgets, this)
62
62
  this._virtualRootWidget = virtualRootWidget
63
63
 
64
64
  try {
@@ -122,7 +122,7 @@ export function createComponent(key, behaviors, properties, events, handler, dat
122
122
  },
123
123
 
124
124
  methods: {
125
- ...createEventHandlers(evtListeners, context),
125
+ ...createEventHandlers(evtListeners),
126
126
  ...mergeRenderer,
127
127
  getWeAppInst() {
128
128
  const $comp = this.$WEAPPS_COMP
@@ -1,10 +1,11 @@
1
1
  import { observable } from 'mobx';
2
2
  import { createComputed, createEventHandlers, checkAuth } from './util';
3
- import { createWidgets, createInitData, disposeWidget } from './widget';
3
+ import { createWidgets, createInitData, disposeWidget, ID_SEPARATOR } from './widget';
4
4
  import mergeRenderer from './merge-renderer';
5
5
  import { createDataset, EXTRA_API, createStateDataSourceVar, generateParamsParser, setConfig } from '../datasources/index';
6
6
  import { runWatchers } from './watch'
7
7
  import lodashGet from 'lodash.get';
8
+ import { getMpEventHandlerName } from "./util";
8
9
 
9
10
  export function createPage(
10
11
  id,
@@ -19,27 +20,18 @@ export function createPage(
19
20
  app,
20
21
  handler,
21
22
  pageContext = {},
22
- context,
23
23
  pageAttributes
24
24
  ) {
25
- const evtHandlers = createEventHandlers(evtListeners, context);
25
+ const evtHandlers = createEventHandlers(evtListeners);
26
26
 
27
- function extractLifecyles() {
27
+ function extractLifecycles() {
28
28
  const result = {};
29
29
  Object.keys(lifecycle).map(name => {
30
30
  result[name] = function () {
31
31
  return lifecycle[name].apply(this.getWeAppInst(), arguments)
32
32
  }
33
33
  })
34
- // const nameMaps = [
35
- // ['onReady', 'onPageReady'],
36
- // ];
37
- // nameMaps.forEach(e => {
38
- // if (!result[e[0]] && result[e[1]]) {
39
- // result[e[0]] = result[e[1]];
40
- // delete result[e[1]];
41
- // }
42
- // });
34
+
43
35
  result['onShareAppMessage'] = (res) => {
44
36
  if (res?.from === 'button' && res?.target?.dataset?.weda_share_info) {
45
37
  return res?.target?.dataset?.weda_share_info;
@@ -77,14 +69,14 @@ export function createPage(
77
69
  if (!$page.componentMethods) {
78
70
  $page.componentMethods = {};
79
71
  }
80
- const [id, index = 0] = e.target.id.split('-');
72
+ const [id, index = 0] = e.target.id.split(ID_SEPARATOR);
81
73
  if (!$page.componentMethods[id]) {
82
74
  $page.componentMethods[id] = [];
83
75
  }
84
76
  $page.componentMethods[id][index] = e.detail.methods;
85
77
  };
86
78
  this.__unmnt__ = (e) => {
87
- const [id, index = 0] = e.target.id.split('-');
79
+ const [id, index = 0] = e.target.id.split(ID_SEPARATOR);
88
80
  if ($page.componentMethods) {
89
81
  const components = $page.componentMethods[id];
90
82
  if (components) {
@@ -114,7 +106,7 @@ export function createPage(
114
106
  methods: {
115
107
  _pageActive: true,
116
108
  /** page lifecycles **/
117
- ...extractLifecyles(),
109
+ ...extractLifecycles(),
118
110
  ...evtHandlers,
119
111
  ...mergeRenderer,
120
112
  onLoad(options) {
@@ -129,20 +121,26 @@ export function createPage(
129
121
 
130
122
  const hook = lifecycle.onLoad || lifecycle.onPageLoad;
131
123
  hook && hook.call($page, query);
124
+
125
+ this.invokeEventHandler(id, 'load', {detail: {query}});
132
126
  },
133
127
  onReady() {
134
- const $page = this.getWeAppInst()
128
+ const $page = this.getWeAppInst();
135
129
 
136
- this._disposers.push(...runWatchers(index, this))
130
+ this._disposers.push(...runWatchers(index, this));
131
+
132
+ const hook = lifecycle.onReady || lifecycle.onPageReady;
133
+ hook && hook.call($page);
137
134
 
138
- const hook = lifecycle.onReady || lifecycle.onPageReady
139
- hook && hook.call($page)
135
+ this.invokeEventHandler(id, 'ready');
140
136
  },
141
137
  onUnload() {
142
138
  const $page = this.getWeAppInst()
143
139
 
144
140
  const hook = lifecycle.onUnload || lifecycle.onPageUnload;
145
141
  hook && hook.call($page);
142
+
143
+ this.invokeEventHandler(id, 'unload');
146
144
  },
147
145
  async onShow() {
148
146
  const $page = this.getWeAppInst()
@@ -159,14 +157,22 @@ export function createPage(
159
157
  weDaHasLogin: true,
160
158
  });
161
159
  }
160
+
161
+ this.invokeEventHandler(id, 'show');
162
162
  },
163
163
  onHide() {
164
164
  const $page = this.getWeAppInst()
165
165
  const hook = lifecycle.onHide || lifecycle.onPageHide;
166
166
  hook && hook.call($page);
167
167
  this._pageActive = false;
168
- },
169
168
 
169
+ // 触发页面节点事件
170
+ this.invokeEventHandler(id, 'hide');
171
+ },
172
+ invokeEventHandler(id, triggerName, params = {}) {
173
+ const keyName = getMpEventHandlerName(id, triggerName);
174
+ typeof evtHandlers?.[keyName] === 'function' && evtHandlers[keyName].call(this, params);
175
+ },
170
176
  getWeAppInst() {
171
177
  let $page = this.$WEAPPS_PAGE
172
178
  if ($page) { return $page }
@@ -192,7 +198,7 @@ export function createPage(
192
198
  });
193
199
  };
194
200
 
195
- const { rootWidget } = createWidgets(widgetProps, dataBinds, $page.widgets, context, this)
201
+ const { rootWidget } = createWidgets(widgetProps, dataBinds, $page.widgets, this)
196
202
  $page._rootWidget = rootWidget
197
203
 
198
204
  $page.invokeComponentMethod = ({ component, method, params }) => {
@@ -1,6 +1,6 @@
1
1
  import { observable, autorun, untracked } from 'mobx';
2
2
  import { styleToCss } from './style';
3
- import { getDeep } from './util';
3
+ import { getDeep, generateDataContext } from './util';
4
4
  import { compLowcodes, create$comp } from './weapp-component';
5
5
  import EventEmitter from './event-emitter';
6
6
  import lodashSet from 'lodash.set';
@@ -23,7 +23,7 @@ function basePullAt(array, indexes) {
23
23
 
24
24
  function remove(array, predicate) {
25
25
  const result = [];
26
- if (!(array != null && array.length)) {
26
+ if (!array?.length) {
27
27
  return result;
28
28
  }
29
29
  let index = -1;
@@ -65,6 +65,7 @@ function resolveWidgetProp(props) {
65
65
  '_parentId',
66
66
  'id',
67
67
  '_order',
68
+ '_scope',
68
69
  'widgetType',
69
70
  '$comp',
70
71
  ];
@@ -82,7 +83,7 @@ export function resolveWidgetData(props) {
82
83
  return props.map(resolveWidgetData);
83
84
  }
84
85
 
85
- export function createWidgets(widgetProps, dataBinds, widgetHolder, context, ownerMpInst) {
86
+ export function createWidgets(widgetProps, dataBinds, widgetHolder, ownerMpInst) {
86
87
  const rootNode = createWidgetDataTree(widgetProps, dataBinds);
87
88
  const failedBinds = [];
88
89
  const result = createSubWidgetTree(
@@ -95,7 +96,6 @@ export function createWidgets(widgetProps, dataBinds, widgetHolder, context, own
95
96
  null,
96
97
  failedBinds,
97
98
  undefined,
98
- context,
99
99
  );
100
100
  retryFailedBinds(failedBinds, true);
101
101
  return result;
@@ -117,12 +117,11 @@ function createSubWidgetTree(
117
117
  ownerForWidgetHolder = null,
118
118
  failedBinds = [],
119
119
  defaultParent = { children: observable([]), _disposers: [] },
120
- context,
121
120
  ) {
122
121
  const indexPostfix = (forItems.lists || [])
123
122
  .slice()
124
123
  .reverse()
125
- .map((list) => idSeparator + list.currentIndex)
124
+ .map((list) => ID_SEPARATOR + list.currentIndex)
126
125
  .join('');
127
126
 
128
127
  // traverse down the tree to set up all widgets
@@ -150,7 +149,7 @@ function createSubWidgetTree(
150
149
  if (parentNode) {
151
150
  parentWidget = widgetHolder[parentNode.id] || ownerForWidgetHolder[parentNode.id];
152
151
  }
153
- w = createAWidget(widgetProps[node.id], node.id + indexPostfix, parentWidget, ownerMpInst);
152
+ w = createAWidget(widgetProps[node.id], node.id, indexPostfix, parentWidget, ownerMpInst);
154
153
  w._key = key;
155
154
  if (!parentWidget) {
156
155
  defaultParent.children.push(w);
@@ -159,7 +158,7 @@ function createSubWidgetTree(
159
158
  } else {
160
159
  disposeWidget(existedWidget, true);
161
160
  }
162
- setUpWidgetDataBinds(w, dataBinds[node.id], forItems, failedBinds, ownerMpInst.getWeAppInst(), context);
161
+ setUpWidgetDataBinds(w, dataBinds[node.id], forItems, failedBinds, ownerMpInst.getWeAppInst());
163
162
  widgetHolder[node.id] = w;
164
163
  } else if (!existedWidget) {
165
164
  const len = parentForWidgetArr.push(observable([]));
@@ -175,17 +174,7 @@ function createSubWidgetTree(
175
174
  if (node.forCount === curForNode.forCount + 1 && dataBinds[node.id] && dataBinds[node.id]._waFor) {
176
175
  // find the node bound with next level for
177
176
  const parent = node.parent ? widgetHolder[node.parent.id] : defaultParent;
178
- const dispose = runFor(
179
- node,
180
- widgetProps,
181
- dataBinds,
182
- ownerMpInst,
183
- forItems,
184
- widgetHolder,
185
- failedBinds,
186
- parent,
187
- context,
188
- );
177
+ const dispose = runFor(node, widgetProps, dataBinds, ownerMpInst, forItems, widgetHolder, failedBinds, parent);
189
178
  parent._disposers.push(dispose); // Add the for bind dispose to the parent node of forNode
190
179
  }
191
180
  });
@@ -222,7 +211,6 @@ function runFor(
222
211
  ownerForWidgetHolder,
223
212
  failedBinds,
224
213
  defaultParent,
225
- context,
226
214
  ) {
227
215
  const nodeId = curForNode.id;
228
216
  const { _waForKey } = curForNode.value;
@@ -231,13 +219,17 @@ function runFor(
231
219
  let forList = [];
232
220
  try {
233
221
  clearTimeout(_FOR_ERROR_CACHE_MAP[nodeId]);
222
+
223
+ const $instance = ownerMpInst.getWeAppInst();
224
+ const dataContext = generateDataContext(defaultParent);
225
+
234
226
  forList = dataBinds[nodeId]._waFor.call(
235
- ownerMpInst.getWeAppInst(),
236
- ownerMpInst.getWeAppInst(),
227
+ $instance,
228
+ $instance,
237
229
  forItems.lists,
238
230
  forItems.itemsById,
239
231
  undefined,
240
- context,
232
+ dataContext,
241
233
  );
242
234
  if (!Array.isArray(forList)) {
243
235
  forList = [];
@@ -300,7 +292,7 @@ function runFor(
300
292
  let { lists = [], itemsById = {} } = forItems;
301
293
  const _forItems = {
302
294
  lists: [{ currentItem: item, currentIndex: index }, ...lists],
303
- itemsById: { ...itemsById, [nodeId]: item, index: { ...itemsById?.index, [nodeId]: index } },
295
+ itemsById: { ...itemsById, [nodeId]: item },
304
296
  };
305
297
  const { rootWidget } = createSubWidgetTree(
306
298
  curForNode,
@@ -312,7 +304,6 @@ function runFor(
312
304
  ownerForWidgetHolder,
313
305
  failedBinds,
314
306
  defaultParent,
315
- context,
316
307
  );
317
308
  rootWidget._forItems = _forItems;
318
309
  });
@@ -322,14 +313,22 @@ function runFor(
322
313
  return dispose;
323
314
  }
324
315
 
325
- function createAWidget(props, id, parent, ownerMpInst) {
316
+ function createAWidget(props, nodeId, indexPostfix, parent, ownerMpInst) {
326
317
  const w = observable(props);
318
+ const id = `${nodeId}${indexPostfix}`;
327
319
 
328
320
  // Builtin props
329
321
  Object.defineProperty(w, 'id', { value: id });
330
322
  const { widgetType } = w;
331
323
  delete w.widgetType;
332
324
  Object.defineProperty(w, 'widgetType', { value: widgetType });
325
+ Object.defineProperty(w, '_scope', {
326
+ value: observable({
327
+ id: nodeId,
328
+ _parent: null,
329
+ dataContext: {},
330
+ }),
331
+ });
333
332
 
334
333
  // w._disposers = []
335
334
  // w.children = []
@@ -339,6 +338,7 @@ function createAWidget(props, id, parent, ownerMpInst) {
339
338
  if (parent) {
340
339
  // w.parent = parent
341
340
  Object.defineProperty(w, 'parent', { value: parent });
341
+ w._scope.parent = parent._scope;
342
342
  parent.children.push(w);
343
343
  }
344
344
  delete w._parentId;
@@ -348,7 +348,7 @@ function createAWidget(props, id, parent, ownerMpInst) {
348
348
  return w;
349
349
  }
350
350
 
351
- function setUpWidgetDataBinds(w, dataBinds, forItems, failedBinds, ctx, context) {
351
+ function setUpWidgetDataBinds(w, dataBinds, forItems, failedBinds, ctx) {
352
352
  Object.keys(dataBinds || {})
353
353
  .sort((a, b) => {
354
354
  return a.length - b.length > 0 ? 1 : -1;
@@ -363,8 +363,11 @@ function setUpWidgetDataBinds(w, dataBinds, forItems, failedBinds, ctx, context)
363
363
  const dispose = autorun((reaction) => {
364
364
  try {
365
365
  clearTimeout(timer);
366
+
367
+ const dataContext = generateDataContext(w);
368
+
366
369
  // Computed data bind in the next tick since data bind may read widgets data
367
- const value = dataBinds[prop].call(ctx, ctx, forItems.lists, forItems.itemsById, undefined, context);
370
+ const value = dataBinds[prop].call(ctx, ctx, forItems.lists, forItems.itemsById, undefined, dataContext);
368
371
  const paths = prop.split('.').filter((key) => !!key);
369
372
  if (paths.length > 1) {
370
373
  // 一定要 untracked 不然爆栈了
@@ -402,10 +405,9 @@ export function findForItemsOfWidget(widget) {
402
405
  if (widget.parent) return findForItemsOfWidget(widget.parent);
403
406
  }
404
407
 
405
- const idSeparator = '-';
406
-
408
+ export const ID_SEPARATOR = '-';
407
409
  export function getWidget(widgets, id) {
408
- return getDeep(widgets, id, idSeparator);
410
+ return getDeep(widgets, id, ID_SEPARATOR);
409
411
  }
410
412
 
411
413
  /**
@@ -445,7 +447,7 @@ function createWidgetDataTree(widgets, dataBinds) {
445
447
  node.forCount = node.parent.forCount;
446
448
  }
447
449
  if (dataBinds[node.id]?._waFor) {
448
- node.forCount++;
450
+ node.forCount += 1;
449
451
  }
450
452
  node.children.map(addForCount);
451
453
  }
@@ -11,7 +11,7 @@ import * as constObj from '../libCommonRes/const'
11
11
  import * as toolsObj from '../libCommonRes/tools'
12
12
 
13
13
  const libCode = '<%= materialName %>'
14
- const context = observable({});
14
+ const $app = new Proxy({}, { get: function(obj, prop){ return app[prop] }});
15
15
 
16
16
  const widgetProps = <%= stringifyObj(widgetProps, {depth: null}) %>
17
17
 
@@ -21,8 +21,8 @@ const evtListeners = {<% Object.entries(eventHandlers).map(([handlerName, listen
21
21
  key: '<%= l.key %>',
22
22
  handler: <% if (l.type == 'rematch') {%> _handler<%= l.handler %> <%} else if (l.type === 'inline') {%> function({event, lists, forItems, $context}, $comp){ <%= l.handler %> } <%} else {%> <%= l.handler %> <%} %>,
23
23
  data: <%= stringifyObj(l.data, {depth: null}) %>,
24
- boundData: {<% Object.entries(l.boundData).map(([prop, expr])=>{%>'<%= prop %>':($comp, lists, forItems, event, $context) => {const $for=forItems;return (
25
- <%= expr === '' ? 'undefined': expr %>
24
+ boundData: {<% Object.entries(l.boundData).map(([prop, bindMeta])=>{%>'<%= prop %>':($comp, lists, forItems, event, $context) => {<%= bindMeta.imports %> return (
25
+ <%= bindMeta.expression === '' ? 'undefined': bindMeta.expression %>
26
26
  )},
27
27
  <%}) %>}
28
28
  },<%})%>
@@ -50,9 +50,9 @@ const handler = {<% handlers.forEach(h => {%>
50
50
  }
51
51
 
52
52
  const dataBinds = {<% Object.entries(dataBinds).map(([id, widgetBinds])=>{%>
53
- <%= id %>: { <% Object.entries(widgetBinds).map(([prop, expr]) => { %>
54
- "<%= prop %>": function ($comp, lists, forItems, event, $context) {const $for=forItems; return (
55
- <%= expr === '' ? 'undefined': expr %>
53
+ <%= id %>: { <% Object.entries(widgetBinds).map(([prop, bindMeta]) => { %>
54
+ "<%= prop %>": function ($comp, lists, forItems, event, $context) {<%= bindMeta.imports %> return (
55
+ <%= bindMeta.expression === '' ? 'undefined': bindMeta.expression %>
56
56
  ); },<% }) %>
57
57
  },<%}) %>
58
58
  }
@@ -60,4 +60,4 @@ const dataBinds = {<% Object.entries(dataBinds).map(([id, widgetBinds])=>{%>
60
60
  const config = <%= JSON.stringify(config || {})%>
61
61
 
62
62
  createComponent('<%= key %>', behaviors, properties, events, handler, dataBinds, evtListeners, widgetProps,
63
- {}, lifeCycle, stateFn, computedFuncs, config, { const: constObj, tools: toolsObj }, libCode, context)
63
+ {}, lifeCycle, stateFn, computedFuncs, config, { const: constObj, tools: toolsObj }, libCode)
@@ -3,7 +3,7 @@
3
3
  "version": "1.0.8",
4
4
  "scripts": {},
5
5
  "dependencies": {
6
- "@cloudbase/weda-client": "0.2.22",
6
+ "@cloudbase/weda-client": "0.2.25",
7
7
  "@cloudbase/weda-cloud-sdk": "1.0.19",
8
8
  "@cloudbase/oauth": "0.1.1-alpha.5",
9
9
  "mobx": "^5.15.4",
@@ -9,7 +9,6 @@ import { <%= pageName %> as handlers } from '../../app/handlers'
9
9
  import { $page } from './api'
10
10
 
11
11
  const $app = new Proxy({}, { get: function(obj, prop){ return app[prop] }});
12
- const context = observable({});
13
12
 
14
13
  const widgetProps = <%= stringifyObj(widgetProps, {depth: null}) %>
15
14
  /** widget event listeners **/
@@ -17,22 +16,22 @@ const evtListeners = {<% Object.entries(eventHanlders).map(([handlerName, listen
17
16
  <%= handlerName%>: [
18
17
  <%listeners.map(l=> { %>{
19
18
  key: '<%= l.key %>',
20
- handler: <% if (l.type === 'rematch') {%> handlers.<%= l.handler %> <%} else if (l.type == 'material') {%> function(...args) { return require('../../materials/<%= l.handlerModule %>/actions/<%= l.handler %>/index').default(...args) } <%} else if (l.type == 'inline') {%> function({event, lists, forItems, $context}, $page){const $for = forItems; return <%= l.handler %> } <%} else {%> <%= l.handler %> <%} %>,
19
+ handler: <% if (l.type === 'rematch') {%> handlers.<%= l.handler %> <%} else if (l.type == 'material') {%> function(...args) { return require('../../materials/<%= l.handlerModule %>/actions/<%= l.handler %>/index').default(...args) } <%} else if (l.type == 'inline') {%> function({event, lists, forItems, $context}){const $for = forItems; const $index=lists?.[0]?.currentIndex; return <%= l.handler %> } <%} else {%> <%= l.handler %> <%} %>,
21
20
  data: <%= stringifyObj(l.data, {depth: null}) %>,
22
- boundData: {<% Object.entries(l.boundData).map(([prop, expr])=>{%>'<%= prop %>':($page, lists, forItems, event, $context) => {const $for = forItems; return (
23
- <%= expr === '' ? 'undefined': expr %>
21
+ boundData: {<% Object.entries(l.boundData).map(([prop, bindMeta])=>{%>'<%= prop %>':($page, lists, forItems, event, $context) => {<%= bindMeta.imports %> return (
22
+ <%= bindMeta.expression === '' ? 'undefined': bindMeta.expression %>
24
23
  )},
25
24
  <%}) %>}
26
25
  },<%})%>
27
26
  ],<%})%>
28
27
  }
28
+
29
29
  const dataBinds = {<% Object.entries(dataBinds).map(([id, widgetBinds])=>{%>
30
- <%= id %>: { <% Object.entries(widgetBinds).map(([prop, expr]) => { %>
31
- "<%= prop %>": function ($page, lists, forItems, event, $context) {const $for = forItems; return (
32
- <%= expr === '' ? 'undefined': expr %>
30
+ <%= id %>: { <% Object.entries(widgetBinds).map(([prop, bindMeta]) => { %>
31
+ "<%= prop %>": function ($page, lists, forItems, event, $context) {<%= bindMeta.imports %> return (
32
+ <%= bindMeta.expression === '' ? 'undefined': bindMeta.expression %>
33
33
  ); },<% }) %>
34
34
  },<%}) %>
35
35
  }
36
36
 
37
-
38
- createPage('<%= pageName %>', '<%= pageUUID %>', widgetProps, {}, lifecyle, state, computed, evtListeners, dataBinds, app, handlers, $page, context, <%= pageAttributes?JSON.stringify(pageAttributes):'{}' %>)
37
+ createPage('<%= pageName %>', '<%= pageUUID %>', widgetProps, {}, lifecyle, state, computed, evtListeners, dataBinds, app, handlers, $page, <%= pageAttributes?JSON.stringify(pageAttributes):'{}' %>)