annil 1.3.0-dev.202312100 → 1.4.0

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.
Files changed (71) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +28 -16
  3. package/dist/api/DefineComponent/collectOptionsForComponent.d.ts +11 -6
  4. package/dist/api/DefineComponent/collectOptionsForComponent.js +30 -35
  5. package/dist/api/DefineComponent/collectOptionsForComponent.js.map +1 -1
  6. package/dist/api/DefineComponent/index.js.map +1 -1
  7. package/dist/api/RootComponent/CustomEvents/test/GetCustomEventDoc.test.js +0 -1
  8. package/dist/api/RootComponent/CustomEvents/test/GetCustomEventDoc.test.js.map +1 -1
  9. package/dist/api/RootComponent/CustomEvents/test/GetFullEventDoc.test.js +0 -1
  10. package/dist/api/RootComponent/CustomEvents/test/GetFullEventDoc.test.js.map +1 -1
  11. package/dist/api/RootComponent/CustomEvents/test/GetShortEventDoc.test.js +0 -1
  12. package/dist/api/RootComponent/CustomEvents/test/GetShortEventDoc.test.js.map +1 -1
  13. package/dist/api/RootComponent/Lifetimes/test/error.test.js +1 -1
  14. package/dist/api/RootComponent/Lifetimes/test/error.test.js.map +1 -1
  15. package/dist/api/RootComponent/Lifetimes/test/normal.test.js +1 -1
  16. package/dist/api/RootComponent/Lifetimes/test/normal.test.js.map +1 -1
  17. package/dist/api/RootComponent/PageLifetimes/PageLifetimesOption.d.ts +1 -1
  18. package/dist/api/RootComponent/index.js +1 -1
  19. package/dist/api/RootComponent/index.js.map +1 -1
  20. package/dist/api/navigateTo.js.map +1 -1
  21. package/dist/behaviors/BComputedAndWatch/computedUpdater.js +2 -11
  22. package/dist/behaviors/BComputedAndWatch/computedUpdater.js.map +1 -1
  23. package/dist/behaviors/BComputedAndWatch/data-tracer.js +3 -0
  24. package/dist/behaviors/BComputedAndWatch/data-tracer.js.map +1 -1
  25. package/dist/behaviors/BComputedAndWatch/getPathsValue.d.ts +1 -2
  26. package/dist/behaviors/BComputedAndWatch/getPathsValue.js +2 -2
  27. package/dist/behaviors/BComputedAndWatch/getPathsValue.js.map +1 -1
  28. package/dist/behaviors/BComputedAndWatch/getPropertiesValue.d.ts +2 -0
  29. package/dist/behaviors/BComputedAndWatch/getPropertiesValue.js +41 -0
  30. package/dist/behaviors/BComputedAndWatch/getPropertiesValue.js.map +1 -0
  31. package/dist/behaviors/BComputedAndWatch/index.js +36 -39
  32. package/dist/behaviors/BComputedAndWatch/index.js.map +1 -1
  33. package/dist/behaviors/BComputedAndWatch/initComputed.d.ts +4 -8
  34. package/dist/behaviors/BComputedAndWatch/initComputed.js +16 -40
  35. package/dist/behaviors/BComputedAndWatch/initComputed.js.map +1 -1
  36. package/dist/behaviors/BComputedAndWatch/isEqual.js.map +1 -1
  37. package/dist/behaviors/BComputedAndWatch/types.d.ts +8 -5
  38. package/dist/behaviors/BStore.js +1 -4
  39. package/dist/behaviors/BStore.js.map +1 -1
  40. package/dist/behaviors/BbeforeCreated.js.map +1 -1
  41. package/dist/thirdLib/index.js +1 -2
  42. package/dist/thirdLib/index.js.map +1 -1
  43. package/dist/utils/InnerMarker.js.map +1 -1
  44. package/dist/utils/isEmptyObject.d.ts +1 -1
  45. package/dist/utils/isEmptyObject.js.map +1 -1
  46. package/package.json +7 -4
  47. package/src/api/DefineComponent/collectOptionsForComponent.ts +57 -58
  48. package/src/api/DefineComponent/index.ts +1 -1
  49. package/src/api/RootComponent/Lifetimes/test/error.test.ts +1 -1
  50. package/src/api/RootComponent/Lifetimes/test/normal.test.ts +1 -1
  51. package/src/api/RootComponent/PageLifetimes/PageLifetimesOption.ts +1 -1
  52. package/src/api/RootComponent/Watch/test/WatchProperties.test.ts +1 -1
  53. package/src/api/RootComponent/index.ts +1 -1
  54. package/src/api/navigateTo.ts +1 -0
  55. package/src/behaviors/BComputedAndWatch/computedUpdater.ts +2 -20
  56. package/src/behaviors/BComputedAndWatch/data-tracer.ts +6 -1
  57. package/src/behaviors/BComputedAndWatch/getPathsValue.ts +2 -4
  58. package/src/behaviors/BComputedAndWatch/getPropertiesValue.ts +57 -0
  59. package/src/behaviors/BComputedAndWatch/index.ts +55 -59
  60. package/src/behaviors/BComputedAndWatch/initComputed.ts +36 -90
  61. package/src/behaviors/BComputedAndWatch/isEqual.ts +1 -0
  62. package/src/behaviors/BComputedAndWatch/types.ts +13 -11
  63. package/src/behaviors/BStore.ts +3 -7
  64. package/src/behaviors/BbeforeCreated.ts +5 -2
  65. package/src/utils/InnerMarker.ts +1 -2
  66. package/src/utils/isEmptyObject.ts +1 -1
  67. package/tsconfig.json +26 -0
  68. package/dist/behaviors/BComputedAndWatch/IsPage.d.ts +0 -2
  69. package/dist/behaviors/BComputedAndWatch/IsPage.js +0 -4
  70. package/dist/behaviors/BComputedAndWatch/IsPage.js.map +0 -1
  71. package/src/behaviors/BComputedAndWatch/IsPage.ts +0 -5
@@ -1,8 +1,7 @@
1
1
  import type { Func } from "hry-types/src/Misc/_api";
2
2
  import { BBeforeCreate } from "../../behaviors/BbeforeCreated";
3
3
  import { BComputedAndWatch } from "../../behaviors/BComputedAndWatch";
4
- import { initComputed } from "../../behaviors/BComputedAndWatch/initComputed";
5
- import type { Instance } from "../../behaviors/BComputedAndWatch/types";
4
+ import type { ComputedCache, Instance } from "../../behaviors/BComputedAndWatch/types";
6
5
  import { BStore } from "../../behaviors/BStore";
7
6
  import type { WMComponent } from "../../types/OfficialTypeAlias";
8
7
  import { INNERMARKER } from "../../utils/InnerMarker";
@@ -20,6 +19,7 @@ import type { PageInstance } from "../RootComponent/Instance/RootComponentInstan
20
19
  import type { LifetimesConstraint } from "../RootComponent/Lifetimes/LifetimesConstraint";
21
20
  import type { MethodsConstraint } from "../RootComponent/Methods/MethodsConstraint";
22
21
  import type { PageLifetimesOption } from "../RootComponent/PageLifetimes/PageLifetimesOption";
22
+ import type { PropertiesConstraint } from "../RootComponent/Properties/PropertiesConstraint";
23
23
  import type { StoreConstraint } from "../RootComponent/Store/StoreConstraint";
24
24
  import type { SubComponentTrueOptions } from "../SubComponent";
25
25
  import type { DefineComponentOption } from ".";
@@ -33,18 +33,21 @@ export type FuncOptions = Record<"pageLifetimes" | "lifetimes" | "watch", Record
33
33
  * 最终传入原生Component的配置项
34
34
  */
35
35
  export type FinalOptionsOfComponent = {
36
+ data: DataConstraint;
37
+ observers: Record<string, Func>;
38
+ behaviors: string[];
39
+ methods: MethodsConstraint & {
40
+ __computedInitCache__?: () => ComputedCache;
41
+ };
36
42
  isPage?: boolean;
37
43
  options?: WMComponent.Options;
38
- properties?: Record<string, any>;
39
- data?: DataConstraint;
44
+ properties?: PropertiesConstraint;
40
45
  store?: StoreConstraint;
41
46
  computed?: ComputedConstraint;
42
- observers?: Record<string, Func>;
43
- behaviors?: string[];
44
- methods?: MethodsConstraint;
45
47
  watch?: Record<string, Func>;
46
48
  lifetimes?: LifetimesConstraint;
47
- } & PageLifetimesOption<false, object>;
49
+ pageLifetimes?: PageLifetimesOption<false, object>["pageLifetimes"];
50
+ };
48
51
 
49
52
  /**
50
53
  * 原生Component会对传入的对象字段匹配的properties字段setData赋值。不符合字段或Page时不会赋值。
@@ -60,7 +63,7 @@ function onLoadReceivedDataHandle(
60
63
  ) {
61
64
  const innerData: string | undefined = option[INNERMARKER.url];
62
65
 
63
- // 情况1为undefined,2为INNERMARKER.url有值但不是本身,说明没有组件中的写了load(因为组件的load提前解析这个参数),3所以innerData等于 INNERMARKER.url即有组件配置了load(提前解析了)
66
+ // 情况1为undefined,2为INNERMARKER.url有值但不是本身,说明是老框架。3所以innerData等于 INNERMARKER.url即有组件配置了load(新框架在pageLifetimes.load中提前解析了)
64
67
  if (innerData === undefined) return;
65
68
  if (innerData !== INNERMARKER.url) {
66
69
  // 需要情况2 需要解析
@@ -105,15 +108,15 @@ function loadReceivedDataHandle(
105
108
  option: Record<typeof INNERMARKER.url, string>,
106
109
  ) {
107
110
  const innerData: string | undefined = option[INNERMARKER.url];
108
- // 未使用自定义的navigateTo 或者在之前的load中已经被解析过了
109
- if (innerData === undefined || innerData == INNERMARKER.url) return;
111
+ // 未使用自定义的navigateTo
112
+ if (innerData === undefined) return;
113
+ // 使用navigateTo API
110
114
  const decodeOption = JSON.parse(decodeURIComponent(innerData));
111
115
 
112
- // 使用navigateTo API
113
116
  for (const key in decodeOption) {
114
117
  option[key] = decodeOption[key];
115
118
  }
116
- // 给onLoad劫持函数一个标记,判断传值来自哪个API
119
+ // 给onLoad劫持函数一个标记,判断在新框架下已经被解析过了
117
120
  option[INNERMARKER.url] = INNERMARKER.url;
118
121
  }
119
122
  /**
@@ -121,8 +124,10 @@ function loadReceivedDataHandle(
121
124
  */
122
125
  /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
123
126
  function hijack(config: object, field: string, before: Func[] = [], after: Func[] = []) {
127
+ // @ts-ignore 隐式索引
124
128
  const originalFunc: Func | undefined = config[field];
125
129
 
130
+ // @ts-ignore 隐式索引
126
131
  config[field] = function(...args: any[]) {
127
132
  before.forEach(func => func.call(this, ...args));
128
133
 
@@ -150,9 +155,10 @@ function InternalFieldProtection(config: object | undefined, keys: string[]) {
150
155
  /**
151
156
  * 把函数配置放入一个配置中依次运行
152
157
  */
153
- function _funcConfigHandle(methodsConfig: object, configList: Record<string, Func[]>) {
158
+ function _funcOptionsHandle(config: object, configList: Record<string, Func[]>) {
154
159
  for (const key in configList) {
155
- methodsConfig[key] = function(...args: unknown[]) {
160
+ // @ts-ignore 隐式索引
161
+ config[key] = function(...args: unknown[]) {
156
162
  configList[key].forEach(ele => ele.call(this, ...args));
157
163
  };
158
164
  }
@@ -160,27 +166,27 @@ function _funcConfigHandle(methodsConfig: object, configList: Record<string, Fun
160
166
  /**
161
167
  * 把函数列表配置放入一个配置中循环一次运行
162
168
  */
163
- function funcConfigHandle(
169
+ function funcOptionsHandle(
164
170
  finalOptionsForComponent: FinalOptionsOfComponent,
165
171
  isPage: boolean | undefined,
166
172
  funcOptions: FuncOptions,
167
173
  ) {
168
- // 测试框架无法测试page情形
169
174
  /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
170
175
  if (isPage) {
171
176
  // 页面时 生命周期方法(即 on 开头的方法),(https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/component.html)
172
- funcOptions.pageLifetimes && _funcConfigHandle(finalOptionsForComponent.methods ||= {}, funcOptions.pageLifetimes);
177
+ !(isEmptyObject(funcOptions.pageLifetimes))
178
+ && _funcOptionsHandle(finalOptionsForComponent.methods, funcOptions.pageLifetimes);
173
179
  } else {
174
180
  // 组件时
175
- funcOptions.pageLifetimes
176
- && _funcConfigHandle(finalOptionsForComponent.pageLifetimes ||= {}, funcOptions.pageLifetimes);
181
+ !(isEmptyObject(funcOptions.pageLifetimes))
182
+ && _funcOptionsHandle(finalOptionsForComponent.pageLifetimes ||= {}, funcOptions.pageLifetimes);
177
183
  }
178
- funcOptions.lifetimes && _funcConfigHandle(finalOptionsForComponent.lifetimes ||= {}, funcOptions.lifetimes);
184
+ funcOptions.lifetimes && _funcOptionsHandle(finalOptionsForComponent.lifetimes ||= {}, funcOptions.lifetimes);
179
185
 
180
- funcOptions.watch && _funcConfigHandle(finalOptionsForComponent.watch ||= {}, funcOptions.watch);
186
+ funcOptions.watch && _funcOptionsHandle(finalOptionsForComponent.watch ||= {}, funcOptions.watch);
181
187
  }
182
188
  /**
183
- * 把配置为函数的字段方法收集到funcConfig
189
+ * 把配置为函数的字段方法收集到funcOptions
184
190
  */
185
191
  function funcFieldsCollect(
186
192
  options: SubComponentTrueOptions | RootComponentTrueOptions,
@@ -188,13 +194,14 @@ function funcFieldsCollect(
188
194
  ) {
189
195
  for (const key in funcOptions) {
190
196
  // key = "pageLifetimes" | "lifetimes" | "watch"
197
+ // @ts-ignore 隐式索引
191
198
  if (options[key]) {
199
+ // @ts-ignore 隐式索引
192
200
  for (const _key in options[key]) {
201
+ // @ts-ignore 隐式索引
193
202
  (funcOptions[key][_key] ||= []).push(options[key][_key]);
194
203
  }
195
204
  }
196
-
197
- Reflect.deleteProperty(options, key);
198
205
  }
199
206
  }
200
207
 
@@ -206,12 +213,13 @@ function otherFieldsHandle(
206
213
  rootComponentOptions: RootComponentTrueOptions,
207
214
  ) {
208
215
  for (const key in rootComponentOptions) {
216
+ // @ts-ignore 隐式索引
209
217
  const config = rootComponentOptions[key];
210
- if (Array.isArray(config)) {
211
- // 好像只有behaviors是数组吧.
212
- /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
213
- (finalOptions[key] ||= []).push(...config);
218
+ if (key === "behaviors") {
219
+ // 是不是只有behaviors是数组
220
+ finalOptions[key].push(...config);
214
221
  } else {
222
+ // @ts-ignore 隐式索引
215
223
  Object.assign(finalOptions[key] ||= {}, config);
216
224
  }
217
225
  }
@@ -219,11 +227,8 @@ function otherFieldsHandle(
219
227
  /**
220
228
  * 把events字段放入到componentOptions.methods中
221
229
  */
222
- function eventsHandle(componentOptions: FinalOptionsOfComponent, eventsConfig: EventsConstraint) {
223
- /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
224
- componentOptions.methods ||= {};
225
-
226
- Object.assign(componentOptions.methods, eventsConfig);
230
+ function eventsHandle(methods: FinalOptionsOfComponent["methods"], eventsConfig: EventsConstraint) {
231
+ Object.assign(methods, eventsConfig);
227
232
  }
228
233
  function subComponentsHandle(
229
234
  componentOptions: FinalOptionsOfComponent,
@@ -231,7 +236,7 @@ function subComponentsHandle(
231
236
  funcOptions: FuncOptions,
232
237
  ) {
233
238
  subComponents.forEach((subOption) => {
234
- subOption.events && eventsHandle(componentOptions, subOption.events);
239
+ subOption.events && eventsHandle(componentOptions.methods, subOption.events);
235
240
 
236
241
  funcFieldsCollect(subOption, funcOptions);
237
242
 
@@ -250,21 +255,18 @@ function IsFullCustomEvents(
250
255
  * 把customEvents字段配置变成函数放入到componentOptions.methods中
251
256
  */
252
257
  function customEventsHandle(
253
- componentOptions: FinalOptionsOfComponent,
258
+ methods: FinalOptionsOfComponent["methods"],
254
259
  customEventsConfig: CustomEventConstraint,
255
260
  ) {
256
- /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
257
- componentOptions.methods ||= {};
258
-
259
261
  for (const key in customEventsConfig) {
260
262
  const customEventOptions = customEventsConfig[key];
261
263
 
262
264
  if (IsFullCustomEvents(customEventOptions)) {
263
- componentOptions.methods[key] = function(this: Instance, detail: unknown) {
265
+ methods[key] = function(this: Instance, detail: unknown) {
264
266
  this.triggerEvent(key, detail, customEventOptions.options);
265
267
  };
266
268
  } else {
267
- componentOptions.methods[key] = function(this: Instance, detail: unknown) {
269
+ methods[key] = function(this: Instance, detail: unknown) {
268
270
  this.triggerEvent(key, detail);
269
271
  };
270
272
  }
@@ -281,13 +283,9 @@ function collectRootComponentOption(
281
283
  funcOptions: FuncOptions,
282
284
  rootComponentOptions: RootComponentTrueOptions,
283
285
  ) {
284
- rootComponentOptions.customEvents && customEventsHandle(finalOptions, rootComponentOptions.customEvents);
285
-
286
- delete rootComponentOptions.customEvents;
286
+ rootComponentOptions.customEvents && customEventsHandle(finalOptions.methods, rootComponentOptions.customEvents);
287
287
 
288
- rootComponentOptions.events && eventsHandle(finalOptions, rootComponentOptions.events);
289
-
290
- delete rootComponentOptions.events;
288
+ rootComponentOptions.events && eventsHandle(finalOptions.methods, rootComponentOptions.events);
291
289
 
292
290
  funcFieldsCollect(rootComponentOptions, funcOptions);
293
291
 
@@ -306,15 +304,16 @@ export function collectOptionsForComponent(
306
304
  const rootComponentOption = defineComponentOption.rootComponent;
307
305
  const subComponentsList = defineComponentOption.subComponents;
308
306
  const finalOptionsForComponent: FinalOptionsOfComponent = {
309
- // default options
310
307
  options: {
311
308
  addGlobalClass: true, // "styleIsolation": "apply-shared"
312
309
  multipleSlots: true,
313
310
  pureDataPattern: /^_/,
314
311
  virtualHost: true,
315
312
  },
316
- // default behaviors
317
313
  behaviors: [BStore, BComputedAndWatch],
314
+ methods: {},
315
+ observers: {},
316
+ data: {},
318
317
  };
319
318
  /**
320
319
  * 有些字段配置同时存在根组件和子组件当中(如pageLifetimes,lifetimes,watch字段), 且key相同值类型为函数。funcConfig对象用于收集这些配置为数组形式,最终再一起整合进finalOptionsForComponent配置中。即funcConfig是一个临时中介对象。
@@ -334,25 +333,25 @@ export function collectOptionsForComponent(
334
333
  }
335
334
  // miniprogram-simulate(当前版本 1.6.1) 无法测试页面
336
335
  /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
337
- funcConfigHandle(finalOptionsForComponent, rootComponentOption?.isPage, funcOptions);
336
+ funcOptionsHandle(finalOptionsForComponent, rootComponentOption?.isPage, funcOptions);
338
337
 
339
- finalOptionsForComponent.methods && InternalFieldProtection(finalOptionsForComponent.methods, ["disposer"]);
338
+ InternalFieldProtection(finalOptionsForComponent.methods, ["disposer"]);
340
339
 
340
+ // 对页面传入参数进行处理 老框架劫持页面methods.onLoad,新框架劫持页面pageLifetimes.load
341
341
  /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
342
- finalOptionsForComponent.methods?.onLoad
343
- && hijack(finalOptionsForComponent.methods, "onLoad", [onLoadReceivedDataHandle, initComputed], []);
342
+ finalOptionsForComponent.isPage
343
+ && hijack(finalOptionsForComponent.pageLifetimes ||= {}, "load", [loadReceivedDataHandle], []);
344
344
 
345
345
  /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
346
- finalOptionsForComponent.pageLifetimes?.load
347
- && hijack(finalOptionsForComponent.pageLifetimes, "load", [loadReceivedDataHandle], []);
346
+ hijack(finalOptionsForComponent.methods, "onLoad", [onLoadReceivedDataHandle], []);
348
347
 
349
348
  // hijack(finalOptionsForComponent.lifetimes!, "attached", [pathCheck(defineComponentOption.path)], []);
350
349
 
351
350
  /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
352
- if (finalOptionsForComponent.isPage) {
351
+ finalOptionsForComponent.isPage
353
352
  // 页面时删除预设的虚拟组件字段
354
- Reflect.deleteProperty(finalOptionsForComponent.options!, "virtualHost");
355
- }
353
+ && Reflect.deleteProperty(finalOptionsForComponent.options!, "virtualHost");
354
+
356
355
  // BBeforeCreate在最后面,让BeforeCreate生命周期运行在最终建立组件时。
357
356
  finalOptionsForComponent.behaviors!.push(BBeforeCreate);
358
357
 
@@ -55,6 +55,6 @@ export type DefineComponentOption = {
55
55
  export const DefineComponent: DefineComponentConstructor = function(options): any {
56
56
  // console.log("---------------------------");
57
57
  Component(
58
- collectOptionsForComponent(options as DefineComponentOption),
58
+ collectOptionsForComponent(options as DefineComponentOption) as any,
59
59
  );
60
60
  };
@@ -8,7 +8,7 @@ RootComponent()({
8
8
  ready() {},
9
9
  detached() {},
10
10
  error(err) {
11
- err.cause;
11
+ err.message;
12
12
  },
13
13
  moved() {},
14
14
  // @ts-expect-error 1 错误的声明周期字段报错
@@ -18,7 +18,7 @@ RootComponent()({
18
18
  detached() {
19
19
  },
20
20
  error(err) {
21
- err.cause;
21
+ err.message;
22
22
  },
23
23
  moved() {
24
24
  },
@@ -17,7 +17,7 @@ export type PageLifetimesOption<TIsPage extends boolean, PropertiesDoc extends o
17
17
  * 周期发生在组件attached之后,页面onLoad之前,要求组件为同步组件
18
18
  * 最低基础库: `3.0.2`
19
19
  */
20
- load?: (props: object) => void | Promise<void>;
20
+ load?: (props: object) => void;
21
21
  }
22
22
  >;
23
23
  },
@@ -134,7 +134,7 @@ RootComponent()({
134
134
  optional_obj(newValue, oldValue) {
135
135
  Checking<ReadonlyDeep<Mock_User>, typeof newValue, Test.Pass>;
136
136
 
137
- Checking<ReadonlyDeep<Mock_User> | null, typeof oldValue, Test.Pass>;
137
+ Checking<ReadonlyDeep<Mock_User | null>, typeof oldValue, Test.Pass>;
138
138
  },
139
139
  // 对象的二段key
140
140
  "optional_obj.age"(newValue, oldValue) {
@@ -128,7 +128,7 @@ export function RootComponent<
128
128
  >(): RootComponentConstructor<
129
129
  TComponentDocList
130
130
  > {
131
- return ((options: any) => options as RootComponentTrueOptions) as any;
131
+ return (options: any) => options;
132
132
  }
133
133
 
134
134
  export type RootComponentTrueOptions = {
@@ -56,6 +56,7 @@ function _encodeURIComponent(
56
56
  export function navigateTo<TPageDoc extends PageDoc = never>(
57
57
  option: NoInfer<NavigateToOption<TPageDoc>>,
58
58
  ) {
59
+ // @ts-ignore 隐式索引
59
60
  if (!option["data"]) {
60
61
  return wx.navigateTo(option);
61
62
  } else {
@@ -6,18 +6,12 @@ import { isEqual } from "./isEqual";
6
6
  import type { Instance } from "./types";
7
7
 
8
8
  export function computedUpdater(this: Instance, isUpdated = false): boolean {
9
- // console.log("computedUpdater开始");
10
-
11
- // console.log("循环判断缓存中每个计算属性依赖是否有变化");
12
-
13
9
  for (const key in this.__computedCache__) {
14
- // console.log("当前计算属性为:", key);
15
-
16
10
  const itemCache = this.__computedCache__[key];
17
11
  let changed = false;
18
12
  for (const dep of itemCache.dependences) {
19
13
  // getPathsValue返回的是数组
20
- const curVal = getPathsValue.call(this, dep.paths.join("."))[0];
14
+ const curVal = getPathsValue(this.data, dep.paths.join("."))[0];
21
15
 
22
16
  // 检查依赖是否更新
23
17
  if (!isEqual(curVal, dep.val)) {
@@ -28,19 +22,7 @@ export function computedUpdater(this: Instance, isUpdated = false): boolean {
28
22
  }
29
23
  if (changed) {
30
24
  const newDependences: ComputedDependence[] = [];
31
- // eslint-disable-next-line @typescript-eslint/no-this-alias
32
- const _this = this;
33
- const computedThis = new Proxy({ data: deepProxy(this.data, newDependences) }, {
34
- get(target, key) {
35
- if (key === "data") {
36
- return Reflect.get(target, key);
37
- }
38
-
39
- return Reflect.get(_this, key);
40
- },
41
- });
42
-
43
- const newValue = itemCache.method.call(computedThis);
25
+ const newValue = itemCache.method.call({ data: deepProxy(this.data, newDependences) });
44
26
 
45
27
  // 更新值不会立即再次进入**函数,而是当前**函数运行完毕后触发**函数,
46
28
  this.setData({
@@ -11,7 +11,7 @@ export function deepProxy(
11
11
  // console.log(target, prop);
12
12
 
13
13
  if (prop === "__rawObject__") return target;
14
-
14
+ // @ts-ignore 隐式索引
15
15
  const val = target[prop];
16
16
 
17
17
  // console.log("获取依赖", prop, val);
@@ -28,6 +28,8 @@ export function deepProxy(
28
28
  }
29
29
  const curPath = basePath.concat(prop);
30
30
 
31
+ // console.log(prop, val,'in');
32
+
31
33
  dependences.push({ paths: curPath, val: unwrap(val) });
32
34
 
33
35
  // 自身方法或原型属性不代理
@@ -40,6 +42,9 @@ export function deepProxy(
40
42
 
41
43
  return deepProxy(val, dependences, curPath);
42
44
  },
45
+ set(_target: object, prop: string) {
46
+ throw Error(`${prop}字段是只读的`);
47
+ },
43
48
  };
44
49
 
45
50
  return new Proxy(data, handler);
@@ -1,12 +1,10 @@
1
- import type { Instance } from "./types";
2
-
3
1
  /**
4
2
  * 获取指定paths的值
5
3
  * @param this - 组件实例 Instance
6
4
  * @param paths - 支持多字段(用`,`分开) 例如 'obj.xxx,a,b' 监控了3个字段
7
5
  * @returns unknown[] 每项对应paths每项的值
8
6
  */
9
- export function getPathsValue(this: Instance, paths: string) {
7
+ export function getPathsValue(data: object, paths: string) {
10
8
  const valueList: unknown[] = [];
11
9
 
12
10
  // ['obj.xxx','a','b'].forEach
@@ -19,7 +17,7 @@ export function getPathsValue(this: Instance, paths: string) {
19
17
  } catch (error) {
20
18
  return undefined;
21
19
  }
22
- }, this.data);
20
+ }, data);
23
21
 
24
22
  valueList.push(value);
25
23
  });
@@ -0,0 +1,57 @@
1
+ import type {
2
+ PropertiesConstraint,
3
+ PropertiesTypes,
4
+ RequiredSingle,
5
+ RequiredUnion,
6
+ } from "../../api/RootComponent/Properties/PropertiesConstraint";
7
+
8
+ type PropertiesDefaultValue = "" | 0 | [] | null | false;
9
+
10
+ /* istanbul ignore next */
11
+ function getRequiredSingleValue(
12
+ PropType: RequiredSingle,
13
+ ): PropertiesDefaultValue {
14
+ switch (PropType) {
15
+ case String:
16
+ return "";
17
+ case Number:
18
+ return 0;
19
+ case Array:
20
+ return [];
21
+ case Object:
22
+ return null;
23
+ case Boolean:
24
+ return false;
25
+ default:
26
+ /* istanbul ignore next */
27
+ throw Error(
28
+ "properties字段类型只能为 String | Number | Array | Object | Boolean",
29
+ );
30
+ }
31
+ }
32
+ function IsRequiredSingle(config: PropertiesTypes): config is RequiredSingle {
33
+ return config instanceof Function;
34
+ }
35
+ function IsRequiredUnion(config: PropertiesTypes): config is RequiredUnion {
36
+ return !Reflect.has(config, "value");
37
+ }
38
+ export function getPropertiesValue(propertiesOpt: PropertiesConstraint | undefined): object | undefined {
39
+ if (propertiesOpt === undefined) return;
40
+ const result = {};
41
+ for (const key in propertiesOpt) {
42
+ const config = propertiesOpt[key];
43
+ /* istanbul ignore next */
44
+ if (IsRequiredSingle(config)) {
45
+ // @ts-ignore 隐式索引
46
+ result[key] = getRequiredSingleValue(config);
47
+ } else if (IsRequiredUnion(config)) {
48
+ // @ts-ignore 隐式索引
49
+ result[key] = getRequiredSingleValue(config.type);
50
+ } else {
51
+ // @ts-ignore 隐式索引
52
+ result[key] = config.value;
53
+ }
54
+ }
55
+
56
+ return result;
57
+ }
@@ -1,22 +1,24 @@
1
- import type { Func } from "hry-types/src/Misc/Func";
2
-
1
+ import type { Func } from "hry-types/src/Misc/_api";
3
2
  import type { FinalOptionsOfComponent } from "../../api/DefineComponent/collectOptionsForComponent";
4
3
  import { deepClone } from "../../utils/deepClone";
5
4
  import { deleteProtoField } from "../../utils/deleteProtoField";
6
5
  import { isEmptyObject } from "../../utils/isEmptyObject";
6
+ import { computedUpdater } from "./computedUpdater";
7
7
  import { getPathsValue } from "./getPathsValue";
8
+ import { getPropertiesValue } from "./getPropertiesValue";
8
9
  import { initComputed } from "./initComputed";
9
10
  import { isEqual } from "./isEqual";
10
- import { isPage } from "./IsPage";
11
11
  import type { Instance, WatchOldValue } from "./types";
12
12
  function initWatchOldValue(this: Instance, watchConfig: object): WatchOldValue {
13
13
  const watchOldValue = {};
14
14
  for (const key in watchConfig) {
15
- watchOldValue[key] = deepClone(getPathsValue.call(this, key));
15
+ // @ts-ignore 隐式索引
16
+ watchOldValue[key] = deepClone(getPathsValue(this.data, key));
16
17
  }
17
18
 
18
19
  return watchOldValue;
19
20
  }
21
+
20
22
  /**
21
23
  * 实现
22
24
  * 1. 计算属性初始化在attached之后(前版本在beforeCreate)
@@ -32,60 +34,50 @@ function initWatchOldValue(this: Instance, watchConfig: object): WatchOldValue {
32
34
  */
33
35
 
34
36
  export const BComputedAndWatch = Behavior({
37
+ // @ts-ignore
35
38
  definitionFilter(options: FinalOptionsOfComponent) {
39
+ // 计算属性初始化
40
+ const rawPropertiesValue = getPropertiesValue(options.properties);
41
+ const methodOpt = options.methods;
36
42
  const computedConfig = options.computed;
37
43
 
38
- // computed handle
39
44
  if (computedConfig && !isEmptyObject(computedConfig)) {
40
- /* istanbul ignore next */
41
- options.methods ||= {};
42
-
43
- const methodsConfig = options.methods;
44
-
45
- // 把计算属性配置保留在methods的__computedConfig__字段下带入到组件实例中。
46
- methodsConfig.__computedConfig__ = () => computedConfig;
47
-
48
- const observersConfig = options.observers ||= {};
49
- // 通过observers加入`**`字段来触发计算属性更新
50
- const originalFunc = observersConfig["**"] as Func | undefined;
51
-
52
- observersConfig["**"] = function(this: Instance): undefined {
53
- const computedStatus = this.__computedStatus__;
54
- switch (computedStatus) {
55
- case undefined:
56
- // 1 触发来自attach时或没有计算属性时
57
- originalFunc && /* istanbul ignore next */ originalFunc.call(this);
58
-
59
- break;
60
- case "初始化中":
61
- // 2 触发来自计算属性初始化时的setData,什么都不需要做。 初始化后__computedStatus__变为待更新
62
-
63
- break;
64
- case "待更新":
65
- // 3. 触发来自attached后的setData或properties更新
66
- {
67
- const isUpdated = this.__computedUpdater__();
68
- if (isUpdated) {
69
- // 更新了会再次触发自身转到 4
70
- this.__computedStatus__ = "更新完毕";
71
- } else {
72
- // 无需更新计算属性
73
- originalFunc && /* istanbul ignore next */ originalFunc.call(this);
74
- }
75
- }
76
- break;
77
- case "更新完毕":
78
- {
79
- // 4 来自计算属性更新后的自身回调
80
- // console.log("来自计算属性更新后的自身回调");
81
- this.__computedStatus__ = "待更新";
45
+ const computedCache = initComputed(options, computedConfig, { ...options.data, ...rawPropertiesValue });
82
46
 
47
+ // 把计算属性缓存从方法中带入到实例中,在created周期加入实例后删除
48
+ methodOpt.__computedInitCache__ = () => computedCache;
49
+ }
50
+ const observersConfig = options.observers;
51
+ // 通过observers加入`**`字段来触发计算属性更新
52
+ const originalFunc = observersConfig["**"] as Func | undefined;
53
+
54
+ observersConfig["**"] = function(this: Instance): undefined {
55
+ const computedStatus = this.__computedStatus__;
56
+ switch (computedStatus) {
57
+ case "待更新":
58
+ // 3. 触发来自attached后的setData或properties更新
59
+ {
60
+ const isUpdated = this.__computedUpdater__();
61
+ if (isUpdated) {
62
+ // 更新了会再次触发自身转到 4
63
+ this.__computedStatus__ = "更新完毕";
64
+ } else {
65
+ // 无需更新计算属性
83
66
  originalFunc && /* istanbul ignore next */ originalFunc.call(this);
84
67
  }
85
- break;
86
- }
87
- };
88
- }
68
+ }
69
+ break;
70
+ case "更新完毕":
71
+ {
72
+ // 4 来自计算属性更新后的自身回调
73
+ // console.log("来自计算属性更新后的自身回调");
74
+ this.__computedStatus__ = "待更新";
75
+
76
+ originalFunc && /* istanbul ignore next */ originalFunc.call(this);
77
+ }
78
+ break;
79
+ }
80
+ };
89
81
 
90
82
  // watch handle
91
83
  const watchConfig = options.watch;
@@ -96,6 +88,7 @@ export const BComputedAndWatch = Behavior({
96
88
  // 把watch配置保留在methods的__watchConfig__字段下带入到组件实例中。
97
89
  methodsConfig.__watchConfig__ = () => watchConfig;
98
90
 
91
+ /* istanbul ignore next */
99
92
  const observersConfig = options.observers ||= {};
100
93
  for (const key in watchConfig) {
101
94
  const watchHadle = watchConfig[key];
@@ -114,22 +107,25 @@ export const BComputedAndWatch = Behavior({
114
107
  },
115
108
  lifetimes: {
116
109
  created(this: Instance) {
110
+ // 把计算属性的初始缓存放入实例
111
+ const __computedInitCache__ = this.__computedInitCache__?.();
112
+
113
+ this.__computedCache__ = __computedInitCache__;
114
+
115
+ deleteProtoField(this, "__computedInitCache__");
116
+
117
+ this.__computedStatus__ = "待更新";
118
+
119
+ this.__computedUpdater__ = computedUpdater.bind(this);
120
+
117
121
  // 初始化watch 生成OldValue
118
122
  const watchConfig = this.__watchConfig__?.();
119
123
 
120
124
  deleteProtoField(this, "__watchConfig__");
121
125
 
122
126
  if (watchConfig) {
123
- // 此时计算属性还未初始化,properties还未第一次传入
124
127
  this.__watchOldValue__ = initWatchOldValue.call(this, watchConfig);
125
128
  }
126
129
  },
127
- attached(this: Instance) {
128
- if (!isPage(this)) {
129
- // 组件此时properties已传入
130
- initComputed.call(this);
131
- }
132
- // else 页面在onLoad时传入properties 计算属性初始化逻辑通过onLoadHijack函数完成
133
- },
134
130
  },
135
131
  });