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.
- package/CHANGELOG.md +26 -0
- package/README.md +28 -16
- package/dist/api/DefineComponent/collectOptionsForComponent.d.ts +11 -6
- package/dist/api/DefineComponent/collectOptionsForComponent.js +30 -35
- package/dist/api/DefineComponent/collectOptionsForComponent.js.map +1 -1
- package/dist/api/DefineComponent/index.js.map +1 -1
- package/dist/api/RootComponent/CustomEvents/test/GetCustomEventDoc.test.js +0 -1
- package/dist/api/RootComponent/CustomEvents/test/GetCustomEventDoc.test.js.map +1 -1
- package/dist/api/RootComponent/CustomEvents/test/GetFullEventDoc.test.js +0 -1
- package/dist/api/RootComponent/CustomEvents/test/GetFullEventDoc.test.js.map +1 -1
- package/dist/api/RootComponent/CustomEvents/test/GetShortEventDoc.test.js +0 -1
- package/dist/api/RootComponent/CustomEvents/test/GetShortEventDoc.test.js.map +1 -1
- package/dist/api/RootComponent/Lifetimes/test/error.test.js +1 -1
- package/dist/api/RootComponent/Lifetimes/test/error.test.js.map +1 -1
- package/dist/api/RootComponent/Lifetimes/test/normal.test.js +1 -1
- package/dist/api/RootComponent/Lifetimes/test/normal.test.js.map +1 -1
- package/dist/api/RootComponent/PageLifetimes/PageLifetimesOption.d.ts +1 -1
- package/dist/api/RootComponent/index.js +1 -1
- package/dist/api/RootComponent/index.js.map +1 -1
- package/dist/api/navigateTo.js.map +1 -1
- package/dist/behaviors/BComputedAndWatch/computedUpdater.js +2 -11
- package/dist/behaviors/BComputedAndWatch/computedUpdater.js.map +1 -1
- package/dist/behaviors/BComputedAndWatch/data-tracer.js +3 -0
- package/dist/behaviors/BComputedAndWatch/data-tracer.js.map +1 -1
- package/dist/behaviors/BComputedAndWatch/getPathsValue.d.ts +1 -2
- package/dist/behaviors/BComputedAndWatch/getPathsValue.js +2 -2
- package/dist/behaviors/BComputedAndWatch/getPathsValue.js.map +1 -1
- package/dist/behaviors/BComputedAndWatch/getPropertiesValue.d.ts +2 -0
- package/dist/behaviors/BComputedAndWatch/getPropertiesValue.js +41 -0
- package/dist/behaviors/BComputedAndWatch/getPropertiesValue.js.map +1 -0
- package/dist/behaviors/BComputedAndWatch/index.js +36 -39
- package/dist/behaviors/BComputedAndWatch/index.js.map +1 -1
- package/dist/behaviors/BComputedAndWatch/initComputed.d.ts +4 -8
- package/dist/behaviors/BComputedAndWatch/initComputed.js +16 -40
- package/dist/behaviors/BComputedAndWatch/initComputed.js.map +1 -1
- package/dist/behaviors/BComputedAndWatch/isEqual.js.map +1 -1
- package/dist/behaviors/BComputedAndWatch/types.d.ts +8 -5
- package/dist/behaviors/BStore.js +1 -4
- package/dist/behaviors/BStore.js.map +1 -1
- package/dist/behaviors/BbeforeCreated.js.map +1 -1
- package/dist/thirdLib/index.js +1 -2
- package/dist/thirdLib/index.js.map +1 -1
- package/dist/utils/InnerMarker.js.map +1 -1
- package/dist/utils/isEmptyObject.d.ts +1 -1
- package/dist/utils/isEmptyObject.js.map +1 -1
- package/package.json +7 -4
- package/src/api/DefineComponent/collectOptionsForComponent.ts +57 -58
- package/src/api/DefineComponent/index.ts +1 -1
- package/src/api/RootComponent/Lifetimes/test/error.test.ts +1 -1
- package/src/api/RootComponent/Lifetimes/test/normal.test.ts +1 -1
- package/src/api/RootComponent/PageLifetimes/PageLifetimesOption.ts +1 -1
- package/src/api/RootComponent/Watch/test/WatchProperties.test.ts +1 -1
- package/src/api/RootComponent/index.ts +1 -1
- package/src/api/navigateTo.ts +1 -0
- package/src/behaviors/BComputedAndWatch/computedUpdater.ts +2 -20
- package/src/behaviors/BComputedAndWatch/data-tracer.ts +6 -1
- package/src/behaviors/BComputedAndWatch/getPathsValue.ts +2 -4
- package/src/behaviors/BComputedAndWatch/getPropertiesValue.ts +57 -0
- package/src/behaviors/BComputedAndWatch/index.ts +55 -59
- package/src/behaviors/BComputedAndWatch/initComputed.ts +36 -90
- package/src/behaviors/BComputedAndWatch/isEqual.ts +1 -0
- package/src/behaviors/BComputedAndWatch/types.ts +13 -11
- package/src/behaviors/BStore.ts +3 -7
- package/src/behaviors/BbeforeCreated.ts +5 -2
- package/src/utils/InnerMarker.ts +1 -2
- package/src/utils/isEmptyObject.ts +1 -1
- package/tsconfig.json +26 -0
- package/dist/behaviors/BComputedAndWatch/IsPage.d.ts +0 -2
- package/dist/behaviors/BComputedAndWatch/IsPage.js +0 -4
- package/dist/behaviors/BComputedAndWatch/IsPage.js.map +0 -1
- 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 {
|
|
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?:
|
|
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
|
-
|
|
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
|
|
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
|
|
109
|
-
if (innerData === undefined
|
|
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
|
|
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
|
|
158
|
+
function _funcOptionsHandle(config: object, configList: Record<string, Func[]>) {
|
|
154
159
|
for (const key in configList) {
|
|
155
|
-
|
|
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
|
|
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
|
-
|
|
177
|
+
!(isEmptyObject(funcOptions.pageLifetimes))
|
|
178
|
+
&& _funcOptionsHandle(finalOptionsForComponent.methods, funcOptions.pageLifetimes);
|
|
173
179
|
} else {
|
|
174
180
|
// 组件时
|
|
175
|
-
funcOptions.pageLifetimes
|
|
176
|
-
&&
|
|
181
|
+
!(isEmptyObject(funcOptions.pageLifetimes))
|
|
182
|
+
&& _funcOptionsHandle(finalOptionsForComponent.pageLifetimes ||= {}, funcOptions.pageLifetimes);
|
|
177
183
|
}
|
|
178
|
-
funcOptions.lifetimes &&
|
|
184
|
+
funcOptions.lifetimes && _funcOptionsHandle(finalOptionsForComponent.lifetimes ||= {}, funcOptions.lifetimes);
|
|
179
185
|
|
|
180
|
-
funcOptions.watch &&
|
|
186
|
+
funcOptions.watch && _funcOptionsHandle(finalOptionsForComponent.watch ||= {}, funcOptions.watch);
|
|
181
187
|
}
|
|
182
188
|
/**
|
|
183
|
-
* 把配置为函数的字段方法收集到
|
|
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 (
|
|
211
|
-
//
|
|
212
|
-
|
|
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(
|
|
223
|
-
|
|
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
|
-
|
|
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
|
-
|
|
265
|
+
methods[key] = function(this: Instance, detail: unknown) {
|
|
264
266
|
this.triggerEvent(key, detail, customEventOptions.options);
|
|
265
267
|
};
|
|
266
268
|
} else {
|
|
267
|
-
|
|
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
|
-
|
|
336
|
+
funcOptionsHandle(finalOptionsForComponent, rootComponentOption?.isPage, funcOptions);
|
|
338
337
|
|
|
339
|
-
|
|
338
|
+
InternalFieldProtection(finalOptionsForComponent.methods, ["disposer"]);
|
|
340
339
|
|
|
340
|
+
// 对页面传入参数进行处理 老框架劫持页面methods.onLoad,新框架劫持页面pageLifetimes.load
|
|
341
341
|
/* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
|
|
342
|
-
finalOptionsForComponent.
|
|
343
|
-
&& hijack(finalOptionsForComponent.
|
|
342
|
+
finalOptionsForComponent.isPage
|
|
343
|
+
&& hijack(finalOptionsForComponent.pageLifetimes ||= {}, "load", [loadReceivedDataHandle], []);
|
|
344
344
|
|
|
345
345
|
/* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */
|
|
346
|
-
finalOptionsForComponent.
|
|
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
|
-
|
|
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
|
};
|
|
@@ -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
|
|
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 (
|
|
131
|
+
return (options: any) => options;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
export type RootComponentTrueOptions = {
|
package/src/api/navigateTo.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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(
|
|
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
|
-
},
|
|
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/
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
});
|