diff --git a/jest/beforeCreate/beforeCreate.ts b/jest/beforeCreate/beforeCreate.ts index 7eb03e7..00b1616 100644 --- a/jest/beforeCreate/beforeCreate.ts +++ b/jest/beforeCreate/beforeCreate.ts @@ -8,7 +8,6 @@ const sub = SubComponent { - const id = load(path.resolve(__dirname, "asyncProperties")); // 此处必须传入绝对路径 - const comp = render(id, { requiredUser: null, optionalUser: null }); // 渲染成自定义组件树实例 - - const parent = document.createElement("parent-wrapper"); // 创建挂载(父)节点 - - comp.attach(parent); // attach 到父亲节点上,此时会触发自定义组件的 attached 钩子 - - test("根组件计算属性初始化值", () => { - expect(comp.data.CoptionalUser).toStrictEqual(null); - - expect(comp.data.CrequiredUser).toStrictEqual(null); - - expect(comp.data.age).toBe(21); - }); - - test("子组件计算属性初始化值", () => { - expect(comp.data.compA_user).toStrictEqual(null); - - expect(comp.data.compA_num).toBe(0 + 0 + 1); - }); - - test("properties改变时计算属性重新计算", () => { - comp.setData({ - requiredUser: user, - optionalUser: user, - }); - - // 根组件计算属性 - expect(comp.data.CoptionalUser).toStrictEqual(user); - - expect(comp.data.CrequiredUser).toStrictEqual(user); - - expect(comp.data.age).toBe(30 + 1); - - // 子组件计算属性 - expect(comp.data.compA_user).toStrictEqual(user); - - expect(comp.data.compA_num).toBe(30 + 30 + 1); - }); - - test("properties更新数据与计算属性缓存深度相等时,计算属性重新计算更新", () => { - comp.setData({ - "requiredUser.age": user.age, // 更新子属性 - optionalUser: user, - }); - - // 根组件计算属性与之前相同 - expect(comp.data.CoptionalUser).toStrictEqual(user); - - expect(comp.data.CrequiredUser).toStrictEqual(user); - - expect(comp.data.age).toBe(30 + 1); - - // 子组件计算属性与之前相同 - expect(comp.data.compA_user).toStrictEqual(user); - - expect(comp.data.compA_num).toBe(30 + 30 + 1); - }); -}); diff --git a/jest/computed/asyncProperties/asyncProperties.ts b/jest/computed/asyncProperties/asyncProperties.ts deleted file mode 100644 index 0eedc9c..0000000 --- a/jest/computed/asyncProperties/asyncProperties.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { DefineComponent, type DetailedType, RootComponent, SubComponent } from "../../../src"; -import { type CompDoc, type User, user } from "../../common"; - -const subA = SubComponent()({ - computed: { - // 可引用根组件properties、data和计算字段 - compA_num(): number { - return (this.data.requiredUser?.age || 0) + this.data.num + (this.data.copyPropUser?.age || 0); - }, - compA_user(): User | null { - return this.data.copyPropUser; - }, - }, -}); - -type Root = typeof rootComponent; - -const rootComponent = RootComponent()({ - properties: { - requiredUser: Object as DetailedType, - optionalUser: { - type: Object as DetailedType, - value: user, - }, - optionalUser1: { - type: Object as DetailedType<{ user: { user: User } }>, - value: { user: { user } }, - }, - }, - data: { - num: 1, - }, - computed: { - CoptionalUser1() { - // 为了营造多个依赖字段去触发依赖去重而写。去重时依赖为 ["optionalUser1.user.","optionalUser1.user.user.age."] initComputed.ts的102-104行 - this.data.optionalUser1?.user; - - this.data.optionalUser1?.user.user.age; - - return 123; - }, - /** - * 可引用下面(后写)的计算属性的子字段,对应[initComputed.ts](../../../src/behaviors/BComputedAndWatch/initComputed.ts)中的 情形2 - */ - age() { - // 为了营造2个依赖字段去触发依赖去重而写。初始依赖为 ["copyPropUser","copyPropUser.age"] initComputed.ts的94-96行 - this.data.copyPropUser; - - return (this.data.copyPropUser?.age || 20) + this.data.num; - }, - /** - * 可引用下面(后写)的计算属性,对应[initComputed.ts](../../../src/behaviors/BComputedAndWatch/initComputed.ts)中的 情形1 - */ - copyPropUser() { - return this.data.CrequiredUser; - }, - // 计算属性可引用properties必传字段 对象类型加入null(异步对象数据默认null)。 - CrequiredUser() { - return this.data.requiredUser; - }, - // 计算属性可引用properties选传字段 对象类型加入null(异步对象数据默认null)。 - CoptionalUser() { - return this.data.optionalUser; - }, - }, -}); - -DefineComponent({ - name: "computed", - rootComponent, - subComponents: [subA], -}); diff --git a/jest/computed/asyncProperties/asyncProperties.json b/jest/computed/normal/normal.json similarity index 100% rename from jest/computed/asyncProperties/asyncProperties.json rename to jest/computed/normal/normal.json diff --git a/jest/computed/normal/normal.test.ts b/jest/computed/normal/normal.test.ts new file mode 100644 index 0000000..6458ebd --- /dev/null +++ b/jest/computed/normal/normal.test.ts @@ -0,0 +1,72 @@ +import { load, render, sleep } from "miniprogram-simulate"; +import path from "path"; +import { user } from "../../common"; + +describe("计算属性 --> 一般测试", () => { + const id = load(path.resolve(__dirname, "normal")); // 此处必须传入绝对路径 + const comp = render(id, { requiredUser: user }); // 渲染成自定义组件树实例 + + const parent = document.createElement("parent-wrapper"); // 创建挂载(父)节点 + + comp.attach(parent); // attach 到父亲节点上,此时会触发自定义组件的 attached 钩子 + + test("根组件计算属性初始化值(attached) ", () => { + expect(comp.data.CoptionalUser).toStrictEqual(user); + + expect(comp.data.CoptionalUser).toStrictEqual(user); + + expect(comp.data.copyPropUser).toStrictEqual(user); + + expect(comp.data.age).toBe(30 + 1); + + expect(comp.data.CStoreAge).toBe(20); + }); + + test("子组件计算属性初始化值(attached)", () => { + expect(comp.data.compA_user).toStrictEqual(user); + + expect(comp.data.compA_num).toBe(30 + 1 + 30); + }); + + test("data字段变化时", async () => { + await sleep(100); + + expect(comp.data.age).toStrictEqual(30 + 2); + + expect(comp.data.compA_num).toBe(30 + 2 + 30); + }); + + test("properties字段变化时", async () => { + await sleep(200); + + expect(comp.data.CrequiredUser).toStrictEqual({ name: "zhao", age: 20 }); + + expect(comp.data.copyPropUser).toStrictEqual({ name: "zhao", age: 20 }); + + expect(comp.data.compA_user).toStrictEqual({ name: "zhao", age: 20 }); + + expect(comp.data.age).toBe(20 + 2); + }); + + test("setData改变对象子字段时", async () => { + await sleep(300); + + expect(comp.data.CoptionalUser).toStrictEqual({ name: "lili", age: 50 }); + + expect(comp.data.compA_num).toStrictEqual(50 + 2 + 50); + }); + + test("store字段变化时", async () => { + await sleep(400); + + expect(comp.data.CStoreAge).toBe(30); + }); + + test("properties对象字段为null时", async () => { + await sleep(1000); + + expect(comp.data.CoptionalUser).toBe(null); + + expect(comp.data.compA_num).toStrictEqual(0 + 2 + 0); + }); +}); diff --git a/jest/computed/normal/normal.ts b/jest/computed/normal/normal.ts new file mode 100644 index 0000000..b608bc4 --- /dev/null +++ b/jest/computed/normal/normal.ts @@ -0,0 +1,124 @@ +import { observable } from "mobx"; +import { DefineComponent, type DetailedType, RootComponent, SubComponent } from "../../../src"; +import { type CompDoc, type User, user } from "../../common"; + +const store = observable({ + name: "zhao", + age: 20, + addAge(num: number) { + this.age = this.age + num; + }, +}); + +const subA = SubComponent()({ + computed: { + // 5 可引用根组件properties、data和计算字段 + compA_num(): number { + return (this.data.optionalUser?.age || 0) + this.data.num + (this.data.CoptionalUser?.age || 0); + }, + // 6 可引用根组件properties、data和计算字段 + compA_user(): User | null { + return this.data.copyPropUser; + }, + }, +}); + +type Root = typeof rootComponent; + +const rootComponent = RootComponent()({ + properties: { + requiredUser: Object as DetailedType, + optionalUser: { + type: Object as DetailedType, + value: user, + }, + forCoverage: { + type: Object as DetailedType<{ user: { user: User } }>, + value: { user: { user } }, + }, + }, + data: { + num: 1, + }, + store: { + storeAge: () => store.age, + }, + computed: { + CforCoverage() { + // 为了营造多个依赖字段去触发依赖去重而写。去重时依赖为 ["forCoverage.user.","forCoverage.user.user.age."] initComputed.ts的79-81行 + this.data.forCoverage?.user; + + this.data.forCoverage?.user.user.age; + + return 123; + }, + /** + * 7 可引用store中的数据 + */ + CStoreAge() { + return this.data.storeAge; + }, + /** + * 4 可引用下面(后写)的计算属性的子字段,对应[initComputed.ts](../../../src/behaviors/BComputedAndWatch/initComputed.ts)中的 情形2 + */ + age() { + return (this.data.copyPropUser?.age || 20) + this.data.num; + }, + /** + * 3 可引用下面(后写)的计算属性,对应[initComputed.ts](../../../src/behaviors/BComputedAndWatch/initComputed.ts)中的 情形1 + */ + copyPropUser() { + return this.data.CrequiredUser; + }, + // 2 计算属性可引用properties必传字段 对象类型加入null(异步对象数据默认null)。 + CrequiredUser() { + return this.data.requiredUser; + }, + // 1 计算属性可引用properties选传字段 对象类型加入null(异步对象数据默认null)。 + CoptionalUser() { + this.data.optionalUser?.name; + + this.data.optionalUser; + + return this.data.optionalUser; + }, + }, + lifetimes: { + attached() { + setTimeout(() => { + this.setData({ + num: 2, + }); + }, 100); + + setTimeout(() => { + this.setData({ + requiredUser: { name: "zhao", age: 20 }, + } as any); + }, 200); + + // 改变对象子字段 + setTimeout(() => { + this.setData({ + "optionalUser.age": 50, + } as any); + }, 300); + + setTimeout(() => { + store.addAge(10); + }, 400); + + setTimeout(() => { + this.setData({ + optionalUser: null, + } as any); + }, 1000); + }, + }, +}); + +DefineComponent({ + name: "computed", + rootComponent, + subComponents: [subA], +}); diff --git a/jest/computed/asyncProperties/asyncProperties.wxml b/jest/computed/normal/normal.wxml similarity index 100% rename from jest/computed/asyncProperties/asyncProperties.wxml rename to jest/computed/normal/normal.wxml diff --git a/jest/computed/syncProperties/syncProperties.json b/jest/computed/syncProperties/syncProperties.json deleted file mode 100644 index 467ce29..0000000 --- a/jest/computed/syncProperties/syncProperties.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "component": true -} diff --git a/jest/computed/syncProperties/syncProperties.test.ts b/jest/computed/syncProperties/syncProperties.test.ts deleted file mode 100644 index 0ed9929..0000000 --- a/jest/computed/syncProperties/syncProperties.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { load, render } from "miniprogram-simulate"; -import path from "path"; -import { user } from "../../common"; - -describe("syncProperties-传入非null值的必传对象,选传为空", () => { - const id = load(path.resolve(__dirname, "syncProperties")); // 此处必须传入绝对路径 - const comp = render(id, { requiredUser: user }); // 渲染成自定义组件树实例 - - const parent = document.createElement("parent-wrapper"); // 创建挂载(父)节点 - - comp.attach(parent); // attach 到父亲节点上,此时会触发自定义组件的 attached 钩子 - - test("根组件计算属性初始化值", () => { - expect(comp.data.CrequiredUser).toStrictEqual(user); - - expect(comp.data.CoptionalUser).toStrictEqual(user); - - expect(comp.data.copyPropUser).toStrictEqual(user); - - expect(comp.data.age).toBe(30 + 1); - }); - - test("子组件计算属性初始化值", () => { - expect(comp.data.compA_user).toStrictEqual(user); - - expect(comp.data.compA_num).toBe(30 + 30 + 1); - }); -}); diff --git a/jest/computed/syncProperties/syncProperties.ts b/jest/computed/syncProperties/syncProperties.ts deleted file mode 100644 index eb5b7e9..0000000 --- a/jest/computed/syncProperties/syncProperties.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { DefineComponent, type DetailedType, RootComponent, SubComponent } from "../../../src"; -import { type CompDoc, type User, user } from "../../common"; - -const subA = SubComponent()({ - computed: { - // 可引用根组件properties、data和计算字段 - compA_num(): number { - return this.data.optionalUser!.age! + this.data.num + (this.data.CoptionalUser?.age || 0); - }, - compA_user(): User | null { - return this.data.copyPropUser; - }, - }, -}); - -type Root = typeof rootComponent; - -const rootComponent = RootComponent()({ - properties: { - requiredUser: Object as DetailedType, - optionalUser: { - type: Object as DetailedType, - value: user, - }, - }, - data: { - num: 1, - }, - computed: { - /** - * 可引用下面(后写)的计算属性的子字段,对应[initComputed.ts](../../../src/behaviors/BComputedAndWatch/initComputed.ts)中的 情形2 - */ - age() { - return (this.data.copyPropUser?.age || 20) + this.data.num; - }, - /** - * 可引用下面(后写)的计算属性,对应[initComputed.ts](../../../src/behaviors/BComputedAndWatch/initComputed.ts)中的 情形1 - */ - copyPropUser() { - return this.data.CrequiredUser; - }, - // 计算属性可引用properties必传字段 对象类型加入null(异步对象数据默认null)。 - CrequiredUser() { - return this.data.requiredUser; - }, - // 计算属性可引用properties选传字段 对象类型加入null(异步对象数据默认null)。 - CoptionalUser() { - return this.data.optionalUser; - }, - }, -}); - -DefineComponent({ - name: "computed", - rootComponent, - subComponents: [subA], -}); diff --git a/jest/computed/syncProperties/syncProperties.wxml b/jest/computed/syncProperties/syncProperties.wxml deleted file mode 100644 index e69de29..0000000 diff --git a/jest/computed/userInstance/userInstance.json b/jest/computed/userInstance/userInstance.json deleted file mode 100644 index 467ce29..0000000 --- a/jest/computed/userInstance/userInstance.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "component": true -} diff --git a/jest/computed/userInstance/userInstance.test.ts b/jest/computed/userInstance/userInstance.test.ts deleted file mode 100644 index 6600a63..0000000 --- a/jest/computed/userInstance/userInstance.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { load, render, sleep } from "miniprogram-simulate"; -import path from "path"; -import { user } from "../../common"; - -describe("计算属性可以使用this上的属性和方法", () => { - const id = load(path.resolve(__dirname, "userInstance")); // 此处必须传入绝对路径 - const comp = render(id, { requiredUser: user }); // 渲染成自定义组件树实例 - - const parent = document.createElement("parent-wrapper"); // 创建挂载(父)节点 - - comp.attach(parent); // attach 到父亲节点上,此时会触发自定义组件的 attached 钩子 - // 初始值 - - test("初始化值和改变依赖后的值", async () => { - expect(comp.data.age).toBe(25); - - await sleep(0); - - expect(comp.data.age).toBe(26); - }); -}); diff --git a/jest/computed/userInstance/userInstance.ts b/jest/computed/userInstance/userInstance.ts deleted file mode 100644 index fdcb68b..0000000 --- a/jest/computed/userInstance/userInstance.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { DefineComponent, type DetailedType, RootComponent } from "../../../src"; - -type User = { name: string; age: number; gender: "female" | "male" }; - -const externalNum = 1; -const storeUser = { - name: "xxx", - gender: "female", - Average: 25, -}; -const rootComponent = RootComponent()({ - properties: { - user: { - type: Object as DetailedType, - value: { name: "zhao", age: 18, gender: "female" }, - }, - }, - data: { - gapAge: 5, - }, - store: { - average: () => storeUser.Average, - }, - computed: { - // 可使用this和外部数据,但要特别注意方法的副作用,建议不使用,或使用的方法为纯函数。 - age() { - return Math.round((this.RealAge(this.data.user!.age) + this.data.average) / 2) + externalNum; - }, - }, - methods: { - RealAge(falseAge: number) { - return falseAge + this.data.gapAge; - }, - }, - lifetimes: { - attached() { - setTimeout(() => { - this.setData({ - gapAge: 7, - }); - }, 0); - }, - }, -}); - -DefineComponent({ - name: "computed", - rootComponent, -}); diff --git a/jest/computed/userInstance/userInstance.wxml b/jest/computed/userInstance/userInstance.wxml deleted file mode 100644 index e69de29..0000000 diff --git a/jest/computed/userInstance/userInstance.wxss b/jest/computed/userInstance/userInstance.wxss deleted file mode 100644 index e69de29..0000000 diff --git a/src/api/DefineComponent/collectOptionsForComponent.ts b/src/api/DefineComponent/collectOptionsForComponent.ts index d70083d..e630aec 100644 --- a/src/api/DefineComponent/collectOptionsForComponent.ts +++ b/src/api/DefineComponent/collectOptionsForComponent.ts @@ -1,8 +1,7 @@ import type { Func } from "hry-types/src/Misc/_api"; import { BBeforeCreate } from "../../behaviors/BbeforeCreated"; import { BComputedAndWatch } from "../../behaviors/BComputedAndWatch"; -import { initComputed } from "../../behaviors/BComputedAndWatch/initComputed"; -import type { Instance } from "../../behaviors/BComputedAndWatch/types"; +import type { ComputedCache, Instance } from "../../behaviors/BComputedAndWatch/types"; import { BStore } from "../../behaviors/BStore"; import type { WMComponent } from "../../types/OfficialTypeAlias"; import { INNERMARKER } from "../../utils/InnerMarker"; @@ -20,6 +19,7 @@ import type { PageInstance } from "../RootComponent/Instance/RootComponentInstan import type { LifetimesConstraint } from "../RootComponent/Lifetimes/LifetimesConstraint"; import type { MethodsConstraint } from "../RootComponent/Methods/MethodsConstraint"; import type { PageLifetimesOption } from "../RootComponent/PageLifetimes/PageLifetimesOption"; +import type { PropertiesConstraint } from "../RootComponent/Properties/PropertiesConstraint"; import type { StoreConstraint } from "../RootComponent/Store/StoreConstraint"; import type { SubComponentTrueOptions } from "../SubComponent"; import type { DefineComponentOption } from "."; @@ -33,18 +33,21 @@ export type FuncOptions = Record<"pageLifetimes" | "lifetimes" | "watch", Record * 最终传入原生Component的配置项 */ export type FinalOptionsOfComponent = { + data: DataConstraint; + observers: Record; + behaviors: string[]; + methods: MethodsConstraint & { + __computedInitCache__?: () => ComputedCache; + }; isPage?: boolean; options?: WMComponent.Options; - properties?: Record; - data?: DataConstraint; + properties?: PropertiesConstraint; store?: StoreConstraint; computed?: ComputedConstraint; - observers?: Record; - behaviors?: string[]; - methods?: MethodsConstraint; watch?: Record; lifetimes?: LifetimesConstraint; -} & PageLifetimesOption; + pageLifetimes?: PageLifetimesOption["pageLifetimes"]; +}; /** * 原生Component会对传入的对象字段匹配的properties字段setData赋值。不符合字段或Page时不会赋值。 @@ -60,7 +63,7 @@ function onLoadReceivedDataHandle( ) { const innerData: string | undefined = option[INNERMARKER.url]; - // 情况1为undefined,2为INNERMARKER.url有值但不是本身,说明没有组件中的写了load(因为组件的load提前解析这个参数),3所以innerData等于 INNERMARKER.url即有组件配置了load(提前解析了) + // 情况1为undefined,2为INNERMARKER.url有值但不是本身,说明是老框架。3所以innerData等于 INNERMARKER.url即有组件配置了load(新框架在pageLifetimes.load中提前解析了) if (innerData === undefined) return; if (innerData !== INNERMARKER.url) { // 需要情况2 需要解析 @@ -105,15 +108,15 @@ function loadReceivedDataHandle( option: Record, ) { const innerData: string | undefined = option[INNERMARKER.url]; - // 未使用自定义的navigateTo 或者在之前的load中已经被解析过了 - if (innerData === undefined || innerData == INNERMARKER.url) return; + // 未使用自定义的navigateTo + if (innerData === undefined) return; + // 使用navigateTo API const decodeOption = JSON.parse(decodeURIComponent(innerData)); - // 使用navigateTo API for (const key in decodeOption) { option[key] = decodeOption[key]; } - // 给onLoad劫持函数一个标记,判断传值来自哪个API + // 给onLoad劫持函数一个标记,判断在新框架下已经被解析过了 option[INNERMARKER.url] = INNERMARKER.url; } /** @@ -150,9 +153,9 @@ function InternalFieldProtection(config: object | undefined, keys: string[]) { /** * 把函数配置放入一个配置中依次运行 */ -function _funcConfigHandle(methodsConfig: object, configList: Record) { +function _funcOptionsHandle(config: object, configList: Record) { for (const key in configList) { - methodsConfig[key] = function(...args: unknown[]) { + config[key] = function(...args: unknown[]) { configList[key].forEach(ele => ele.call(this, ...args)); }; } @@ -160,27 +163,27 @@ function _funcConfigHandle(methodsConfig: object, configList: Record { - subOption.events && eventsHandle(componentOptions, subOption.events); + subOption.events && eventsHandle(componentOptions.methods, subOption.events); funcFieldsCollect(subOption, funcOptions); @@ -250,21 +247,18 @@ function IsFullCustomEvents( * 把customEvents字段配置变成函数放入到componentOptions.methods中 */ function customEventsHandle( - componentOptions: FinalOptionsOfComponent, + methods: FinalOptionsOfComponent["methods"], customEventsConfig: CustomEventConstraint, ) { - /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */ - componentOptions.methods ||= {}; - for (const key in customEventsConfig) { const customEventOptions = customEventsConfig[key]; if (IsFullCustomEvents(customEventOptions)) { - componentOptions.methods[key] = function(this: Instance, detail: unknown) { + methods[key] = function(this: Instance, detail: unknown) { this.triggerEvent(key, detail, customEventOptions.options); }; } else { - componentOptions.methods[key] = function(this: Instance, detail: unknown) { + methods[key] = function(this: Instance, detail: unknown) { this.triggerEvent(key, detail); }; } @@ -281,13 +275,9 @@ function collectRootComponentOption( funcOptions: FuncOptions, rootComponentOptions: RootComponentTrueOptions, ) { - rootComponentOptions.customEvents && customEventsHandle(finalOptions, rootComponentOptions.customEvents); - - delete rootComponentOptions.customEvents; + rootComponentOptions.customEvents && customEventsHandle(finalOptions.methods, rootComponentOptions.customEvents); - rootComponentOptions.events && eventsHandle(finalOptions, rootComponentOptions.events); - - delete rootComponentOptions.events; + rootComponentOptions.events && eventsHandle(finalOptions.methods, rootComponentOptions.events); funcFieldsCollect(rootComponentOptions, funcOptions); @@ -306,15 +296,16 @@ export function collectOptionsForComponent( const rootComponentOption = defineComponentOption.rootComponent; const subComponentsList = defineComponentOption.subComponents; const finalOptionsForComponent: FinalOptionsOfComponent = { - // default options options: { addGlobalClass: true, // "styleIsolation": "apply-shared" multipleSlots: true, pureDataPattern: /^_/, virtualHost: true, }, - // default behaviors behaviors: [BStore, BComputedAndWatch], + methods: {}, + observers: {}, + data: {}, }; /** * 有些字段配置同时存在根组件和子组件当中(如pageLifetimes,lifetimes,watch字段), 且key相同值类型为函数。funcConfig对象用于收集这些配置为数组形式,最终再一起整合进finalOptionsForComponent配置中。即funcConfig是一个临时中介对象。 @@ -334,25 +325,25 @@ export function collectOptionsForComponent( } // miniprogram-simulate(当前版本 1.6.1) 无法测试页面 /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */ - funcConfigHandle(finalOptionsForComponent, rootComponentOption?.isPage, funcOptions); + funcOptionsHandle(finalOptionsForComponent, rootComponentOption?.isPage, funcOptions); - finalOptionsForComponent.methods && InternalFieldProtection(finalOptionsForComponent.methods, ["disposer"]); + InternalFieldProtection(finalOptionsForComponent.methods, ["disposer"]); + // 对页面传入参数进行处理 老框架劫持页面methods.onLoad,新框架劫持页面pageLifetimes.load /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */ - finalOptionsForComponent.methods?.onLoad - && hijack(finalOptionsForComponent.methods, "onLoad", [onLoadReceivedDataHandle, initComputed], []); + finalOptionsForComponent.isPage + && hijack(finalOptionsForComponent.pageLifetimes ||= {}, "load", [loadReceivedDataHandle], []); /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */ - finalOptionsForComponent.pageLifetimes?.load - && hijack(finalOptionsForComponent.pageLifetimes, "load", [loadReceivedDataHandle], []); + hijack(finalOptionsForComponent.methods, "onLoad", [onLoadReceivedDataHandle], []); // hijack(finalOptionsForComponent.lifetimes!, "attached", [pathCheck(defineComponentOption.path)], []); /* istanbul ignore next: miniprogram-simulate(当前版本 1.6.1) 无法测试页面 */ - if (finalOptionsForComponent.isPage) { + finalOptionsForComponent.isPage // 页面时删除预设的虚拟组件字段 - Reflect.deleteProperty(finalOptionsForComponent.options!, "virtualHost"); - } + && Reflect.deleteProperty(finalOptionsForComponent.options!, "virtualHost"); + // BBeforeCreate在最后面,让BeforeCreate生命周期运行在最终建立组件时。 finalOptionsForComponent.behaviors!.push(BBeforeCreate); diff --git a/src/api/DefineComponent/index.ts b/src/api/DefineComponent/index.ts index 93ec08c..ff2ca89 100644 --- a/src/api/DefineComponent/index.ts +++ b/src/api/DefineComponent/index.ts @@ -55,6 +55,6 @@ export type DefineComponentOption = { export const DefineComponent: DefineComponentConstructor = function(options): any { // console.log("---------------------------"); Component( - collectOptionsForComponent(options as DefineComponentOption), + collectOptionsForComponent(options as DefineComponentOption) as any, ); }; diff --git a/src/api/RootComponent/PageLifetimes/PageLifetimesOption.ts b/src/api/RootComponent/PageLifetimes/PageLifetimesOption.ts index 0d83e18..786a8ca 100644 --- a/src/api/RootComponent/PageLifetimes/PageLifetimesOption.ts +++ b/src/api/RootComponent/PageLifetimes/PageLifetimesOption.ts @@ -17,7 +17,7 @@ export type PageLifetimesOption void | Promise; + load?: (props: object) => void; } >; }, diff --git a/src/api/RootComponent/Watch/test/WatchProperties.test.ts b/src/api/RootComponent/Watch/test/WatchProperties.test.ts index 2e9bc41..5515b15 100644 --- a/src/api/RootComponent/Watch/test/WatchProperties.test.ts +++ b/src/api/RootComponent/Watch/test/WatchProperties.test.ts @@ -134,7 +134,7 @@ RootComponent()({ optional_obj(newValue, oldValue) { Checking, typeof newValue, Test.Pass>; - Checking | null, typeof oldValue, Test.Pass>; + Checking, typeof oldValue, Test.Pass>; }, // 对象的二段key "optional_obj.age"(newValue, oldValue) { diff --git a/src/api/RootComponent/index.ts b/src/api/RootComponent/index.ts index 371304d..ca296da 100644 --- a/src/api/RootComponent/index.ts +++ b/src/api/RootComponent/index.ts @@ -128,7 +128,7 @@ export function RootComponent< >(): RootComponentConstructor< TComponentDocList > { - return ((options: any) => options as RootComponentTrueOptions) as any; + return (options: any) => options; } export type RootComponentTrueOptions = { diff --git a/src/behaviors/BComputedAndWatch/IsPage.ts b/src/behaviors/BComputedAndWatch/IsPage.ts deleted file mode 100644 index 97712c2..0000000 --- a/src/behaviors/BComputedAndWatch/IsPage.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { ComponentInstance, PageInstance } from "../../api/RootComponent/Instance/RootComponentInstance"; - -export function isPage(Ins: ComponentInstance | PageInstance): Ins is PageInstance { - return typeof (Ins as PageInstance).route === "string"; -} diff --git a/src/behaviors/BComputedAndWatch/computedUpdater.ts b/src/behaviors/BComputedAndWatch/computedUpdater.ts index 08beb80..56d6c76 100644 --- a/src/behaviors/BComputedAndWatch/computedUpdater.ts +++ b/src/behaviors/BComputedAndWatch/computedUpdater.ts @@ -6,18 +6,12 @@ import { isEqual } from "./isEqual"; import type { Instance } from "./types"; export function computedUpdater(this: Instance, isUpdated = false): boolean { - // console.log("computedUpdater开始"); - - // console.log("循环判断缓存中每个计算属性依赖是否有变化"); - for (const key in this.__computedCache__) { - // console.log("当前计算属性为:", key); - const itemCache = this.__computedCache__[key]; let changed = false; for (const dep of itemCache.dependences) { // getPathsValue返回的是数组 - const curVal = getPathsValue.call(this, dep.paths.join("."))[0]; + const curVal = getPathsValue(this.data, dep.paths.join("."))[0]; // 检查依赖是否更新 if (!isEqual(curVal, dep.val)) { @@ -28,19 +22,7 @@ export function computedUpdater(this: Instance, isUpdated = false): boolean { } if (changed) { const newDependences: ComputedDependence[] = []; - // eslint-disable-next-line @typescript-eslint/no-this-alias - const _this = this; - const computedThis = new Proxy({ data: deepProxy(this.data, newDependences) }, { - get(target, key) { - if (key === "data") { - return Reflect.get(target, key); - } - - return Reflect.get(_this, key); - }, - }); - - const newValue = itemCache.method.call(computedThis); + const newValue = itemCache.method.call({ data: deepProxy(this.data, newDependences) }); // 更新值不会立即再次进入**函数,而是当前**函数运行完毕后触发**函数, this.setData({ diff --git a/src/behaviors/BComputedAndWatch/data-tracer.ts b/src/behaviors/BComputedAndWatch/data-tracer.ts index b14950a..6bd1f98 100644 --- a/src/behaviors/BComputedAndWatch/data-tracer.ts +++ b/src/behaviors/BComputedAndWatch/data-tracer.ts @@ -28,6 +28,8 @@ export function deepProxy( } const curPath = basePath.concat(prop); + // console.log(prop, val,'in'); + dependences.push({ paths: curPath, val: unwrap(val) }); // 自身方法或原型属性不代理 diff --git a/src/behaviors/BComputedAndWatch/getPathsValue.ts b/src/behaviors/BComputedAndWatch/getPathsValue.ts index 324db54..bdcd5ef 100644 --- a/src/behaviors/BComputedAndWatch/getPathsValue.ts +++ b/src/behaviors/BComputedAndWatch/getPathsValue.ts @@ -1,12 +1,10 @@ -import type { Instance } from "./types"; - /** * 获取指定paths的值 * @param this - 组件实例 Instance * @param paths - 支持多字段(用`,`分开) 例如 'obj.xxx,a,b' 监控了3个字段 * @returns unknown[] 每项对应paths每项的值 */ -export function getPathsValue(this: Instance, paths: string) { +export function getPathsValue(data: object, paths: string) { const valueList: unknown[] = []; // ['obj.xxx','a','b'].forEach @@ -19,7 +17,7 @@ export function getPathsValue(this: Instance, paths: string) { } catch (error) { return undefined; } - }, this.data); + }, data); valueList.push(value); }); diff --git a/src/behaviors/BComputedAndWatch/getPropertiesValue.ts b/src/behaviors/BComputedAndWatch/getPropertiesValue.ts new file mode 100644 index 0000000..60e2a96 --- /dev/null +++ b/src/behaviors/BComputedAndWatch/getPropertiesValue.ts @@ -0,0 +1,54 @@ +import type { + PropertiesConstraint, + PropertiesTypes, + RequiredSingle, + RequiredUnion, +} from "../../api/RootComponent/Properties/PropertiesConstraint"; + +type PropertiesDefaultValue = "" | 0 | [] | null | false; + +/* istanbul ignore next */ +function getRequiredSingleValue( + PropType: RequiredSingle, +): PropertiesDefaultValue { + switch (PropType) { + case String: + return ""; + case Number: + return 0; + case Array: + return []; + case Object: + return null; + case Boolean: + return false; + default: + /* istanbul ignore next */ + throw Error( + "properties字段类型只能为 String | Number | Array | Object | Boolean", + ); + } +} +function IsRequiredSingle(config: PropertiesTypes): config is RequiredSingle { + return config instanceof Function; +} +function IsRequiredUnion(config: PropertiesTypes): config is RequiredUnion { + return !Reflect.has(config, "value"); +} +export function getPropertiesValue(propertiesOpt: PropertiesConstraint | undefined): object | undefined { + if (propertiesOpt === undefined) return; + const result = {}; + for (const key in propertiesOpt) { + const config = propertiesOpt[key]; + /* istanbul ignore next */ + if (IsRequiredSingle(config)) { + result[key] = getRequiredSingleValue(config); + } else if (IsRequiredUnion(config)) { + result[key] = getRequiredSingleValue(config.type); + } else { + result[key] = config.value; + } + } + + return result; +} diff --git a/src/behaviors/BComputedAndWatch/index.ts b/src/behaviors/BComputedAndWatch/index.ts index 368992c..2dd340a 100644 --- a/src/behaviors/BComputedAndWatch/index.ts +++ b/src/behaviors/BComputedAndWatch/index.ts @@ -1,22 +1,23 @@ -import type { Func } from "hry-types/src/Misc/Func"; - +import type { Func } from "hry-types/src/Misc/_api"; import type { FinalOptionsOfComponent } from "../../api/DefineComponent/collectOptionsForComponent"; import { deepClone } from "../../utils/deepClone"; import { deleteProtoField } from "../../utils/deleteProtoField"; import { isEmptyObject } from "../../utils/isEmptyObject"; +import { computedUpdater } from "./computedUpdater"; import { getPathsValue } from "./getPathsValue"; +import { getPropertiesValue } from "./getPropertiesValue"; import { initComputed } from "./initComputed"; import { isEqual } from "./isEqual"; -import { isPage } from "./IsPage"; import type { Instance, WatchOldValue } from "./types"; function initWatchOldValue(this: Instance, watchConfig: object): WatchOldValue { const watchOldValue = {}; for (const key in watchConfig) { - watchOldValue[key] = deepClone(getPathsValue.call(this, key)); + watchOldValue[key] = deepClone(getPathsValue(this.data, key)); } return watchOldValue; } + /** * 实现 * 1. 计算属性初始化在attached之后(前版本在beforeCreate) @@ -32,60 +33,50 @@ function initWatchOldValue(this: Instance, watchConfig: object): WatchOldValue { */ export const BComputedAndWatch = Behavior({ + // @ts-ignore definitionFilter(options: FinalOptionsOfComponent) { + // 计算属性初始化 + const rawPropertiesValue = getPropertiesValue(options.properties); + const methodOpt = options.methods; const computedConfig = options.computed; - // computed handle if (computedConfig && !isEmptyObject(computedConfig)) { - /* istanbul ignore next */ - options.methods ||= {}; - - const methodsConfig = options.methods; - - // 把计算属性配置保留在methods的__computedConfig__字段下带入到组件实例中。 - methodsConfig.__computedConfig__ = () => computedConfig; - - const observersConfig = options.observers ||= {}; - // 通过observers加入`**`字段来触发计算属性更新 - const originalFunc = observersConfig["**"] as Func | undefined; - - observersConfig["**"] = function(this: Instance): undefined { - const computedStatus = this.__computedStatus__; - switch (computedStatus) { - case undefined: - // 1 触发来自attach时或没有计算属性时 - originalFunc && /* istanbul ignore next */ originalFunc.call(this); - - break; - case "初始化中": - // 2 触发来自计算属性初始化时的setData,什么都不需要做。 初始化后__computedStatus__变为待更新 - - break; - case "待更新": - // 3. 触发来自attached后的setData或properties更新 - { - const isUpdated = this.__computedUpdater__(); - if (isUpdated) { - // 更新了会再次触发自身转到 4 - this.__computedStatus__ = "更新完毕"; - } else { - // 无需更新计算属性 - originalFunc && /* istanbul ignore next */ originalFunc.call(this); - } - } - break; - case "更新完毕": - { - // 4 来自计算属性更新后的自身回调 - // console.log("来自计算属性更新后的自身回调"); - this.__computedStatus__ = "待更新"; + const computedCache = initComputed(options, computedConfig, { ...options.data, ...rawPropertiesValue }); + // 把计算属性缓存从方法中带入到实例中,在created周期加入实例后删除 + methodOpt.__computedInitCache__ = () => computedCache; + } + const observersConfig = options.observers; + // 通过observers加入`**`字段来触发计算属性更新 + const originalFunc = observersConfig["**"] as Func | undefined; + + observersConfig["**"] = function(this: Instance): undefined { + const computedStatus = this.__computedStatus__; + switch (computedStatus) { + case "待更新": + // 3. 触发来自attached后的setData或properties更新 + { + const isUpdated = this.__computedUpdater__(); + if (isUpdated) { + // 更新了会再次触发自身转到 4 + this.__computedStatus__ = "更新完毕"; + } else { + // 无需更新计算属性 originalFunc && /* istanbul ignore next */ originalFunc.call(this); } - break; - } - }; - } + } + break; + case "更新完毕": + { + // 4 来自计算属性更新后的自身回调 + // console.log("来自计算属性更新后的自身回调"); + this.__computedStatus__ = "待更新"; + + originalFunc && /* istanbul ignore next */ originalFunc.call(this); + } + break; + } + }; // watch handle const watchConfig = options.watch; @@ -96,6 +87,7 @@ export const BComputedAndWatch = Behavior({ // 把watch配置保留在methods的__watchConfig__字段下带入到组件实例中。 methodsConfig.__watchConfig__ = () => watchConfig; + /* istanbul ignore next */ const observersConfig = options.observers ||= {}; for (const key in watchConfig) { const watchHadle = watchConfig[key]; @@ -114,22 +106,25 @@ export const BComputedAndWatch = Behavior({ }, lifetimes: { created(this: Instance) { + // 把计算属性的初始缓存放入实例 + const __computedInitCache__ = this.__computedInitCache__?.(); + + this.__computedCache__ = __computedInitCache__; + + deleteProtoField(this, "__computedInitCache__"); + + this.__computedStatus__ = "待更新"; + + this.__computedUpdater__ = computedUpdater.bind(this); + // 初始化watch 生成OldValue const watchConfig = this.__watchConfig__?.(); deleteProtoField(this, "__watchConfig__"); if (watchConfig) { - // 此时计算属性还未初始化,properties还未第一次传入 this.__watchOldValue__ = initWatchOldValue.call(this, watchConfig); } }, - attached(this: Instance) { - if (!isPage(this)) { - // 组件此时properties已传入 - initComputed.call(this); - } - // else 页面在onLoad时传入properties 计算属性初始化逻辑通过onLoadHijack函数完成 - }, }, }); diff --git a/src/behaviors/BComputedAndWatch/initComputed.ts b/src/behaviors/BComputedAndWatch/initComputed.ts index f9c6bf4..6561ec2 100644 --- a/src/behaviors/BComputedAndWatch/initComputed.ts +++ b/src/behaviors/BComputedAndWatch/initComputed.ts @@ -2,17 +2,11 @@ // import type { IsDependOnOthers } from "./data-tracer"; import type { Func } from "hry-types/src/Misc/Func"; -import { deleteProtoField } from "../../utils/deleteProtoField"; -import { computedUpdater } from "./computedUpdater"; +import type { FinalOptionsOfComponent } from "../../api/DefineComponent/collectOptionsForComponent"; import { deepProxy, unwrap } from "./data-tracer"; -import type { ComputedCache, Instance } from "./types"; +import type { ComputedCache, ItemCache } from "./types"; export type ComputedDependence = { paths: string[]; val: unknown }; -type ComputedInfo = { - dependences: ComputedDependence[]; - value: unknown; -}; - /** * 如果依赖列表某项的首个字段值为undefined并且字段为其他计算属性字段 返回false(即被依赖的计算字段写在了依赖他的计算字段后面), 否则返回ComputedInfo。 */ @@ -20,7 +14,7 @@ function isValidDependences(dependences: ComputedDependence[], computedKeys: str for (const { paths: path, val } of dependences) { // 引用值为undefined时 // console.log(path[0]); - if (val === undefined && computedKeys.includes(path[0])) { + if ((val === undefined) && computedKeys.includes(path[0])) { return false; } } @@ -28,49 +22,22 @@ function isValidDependences(dependences: ComputedDependence[], computedKeys: str return true; // 依赖有效 } -export function getComputedInfo( - this: Instance, +export function getItemCache( + initAllData: object, computedKeys: string[], computedFunc: Func, - key: string, -): false | ComputedInfo { - // 建立当前计算字段的依赖 +): false | ItemCache { + // 当前计算字段的依赖列表 const dependences: ComputedDependence[] = []; - let initValue: unknown; - // eslint-disable-next-line @typescript-eslint/no-this-alias - const _this = this; - const computedThis = new Proxy({ data: deepProxy(this.data, dependences) }, { - get(target, key) { - if (key === "data") { - return Reflect.get(target, key); - } - - return Reflect.get(_this, key); - }, - }); - - initValue = computedFunc.call(computedThis); - - // } catch (error) { - // // 为js开发考虑使用了 this.data.xxx.age 当xxx为undefined时 - // if (!isValidDependences(dependences, computedKeys)) { - // console.log(222); + const initValue = computedFunc.call({ data: deepProxy(initAllData, dependences) }); - // // 情形2 依赖了未初始化的计算属性的子属性(会报错) 对应测试文件[NoOptionalProperties.ts](../../../jest/computed/NoOptionalProperties/NoOptionalProperties.test.ts)的age字段 - // return false; - // } - // // 其他错误正常报错 - // throw error; - // } if (isValidDependences(dependences, computedKeys)) { - // 有效的依赖 - initValue = unwrap(initValue); - - this.setData({ - [key]: initValue, - }); - - return { dependences, value: initValue }; + return { + // 去重 避免 如: ` age(){ return this.data.xxx.num + this.data.xxx.str + this.data.xxx} ` 造成的多个依赖相同情况。应就要一个 xxx + dependences: uniqueDependences(dependences), + method: computedFunc, + value: unwrap(initValue), + }; } else { /** * 情形1 依赖了其他未初始化的计算属性(不报错) 对应测试文件[NoOptionalProperties.ts](../../../jest/computed/NoOptionalProperties/NoOptionalProperties.test.ts)的copyPropUser字段 @@ -118,66 +85,44 @@ function uniqueDependences(dependences: ComputedDependence[]): ComputedDependenc return dependences; } + /** - * 初始化计算属性配置返回计算属性缓存 - * @param computedConfig - 计算属性配置 - * @param uninitedkeys - 未初始的计算属性keys - * @param computedCache - 计算属性缓存默认=`{}` - * @returns 计算属性缓存 + * 把计算属性初始值加入到options.data中返回缓存 */ -function _initComputed( - this: Instance, +export function initComputed( + options: FinalOptionsOfComponent, computedConfig: Record, - uninitedkeys: string[], // + initAllData: object, + uninitedkeys: string[] = Object.keys(computedConfig), computedCache: ComputedCache = {}, ): ComputedCache { - // 收集依赖 + // 收集依赖 uninitedkeys不受内部2处重新赋值的影响 for (const key of uninitedkeys) { - const computedInfo = getComputedInfo.call(this, uninitedkeys, computedConfig[key], key); + // uninitedkeys 受2处重新赋值的影响 + const itemCache = getItemCache(initAllData, uninitedkeys, computedConfig[key]); - // 去除完成的依赖key + // 去除当前的key 2 uninitedkeys = uninitedkeys.filter(ele => ele !== key); - if (computedInfo === false) { + if (itemCache === false) { // 把当前依赖不正确的key放到后面去 uninitedkeys.push(key); } else { - computedCache[key] = { - // 去重 避免 如: ` age(){ return this.data.xxx.num + this.data.xxx.str + this.data.xxx} ` 造成的多个依赖相同情况。应就要一个 xxx - dependences: uniqueDependences(computedInfo.dependences), - method: computedConfig[key], - value: computedInfo.value, // 为了watch的oldValue - }; + /* istanbul ignore next */ + const dataOpt = options.data ||= {}; + + dataOpt[key] = itemCache.value; + + initAllData[key] = itemCache.value; + + computedCache[key] = itemCache; } } - // 看uninitedkey是否未空,空表示所有依赖收集完毕直接返回 + // 看uninitedkey(2处的新值)是否未空,空表示所有依赖收集完毕直接返回 if (uninitedkeys.length === 0) { return computedCache; } // uninitedkey不为空,递归 - return _initComputed.call(this, computedConfig, uninitedkeys, computedCache); -} -export function initComputed(this: Instance) { - const computedConfig = this.__computedConfig__?.(); - - deleteProtoField(this, "__computedConfig__"); - - if (computedConfig) { - // 实例加入 __computedUpdateStatus__ 提高性能 - this.__computedStatus__ = "初始化中"; - - // 初始化计算属性(返回缓存) - this.__computedCache__ = _initComputed.call( - this, - computedConfig, - Object.keys(computedConfig), - ); - - // 给原型上加入__computedUpdater__方法 在observers下的'**'配置中触发 - - this.__computedUpdater__ = computedUpdater.bind(this); - - this.__computedStatus__ = "待更新"; - } + return initComputed(options, computedConfig, initAllData, uninitedkeys, computedCache); } diff --git a/src/behaviors/BComputedAndWatch/types.ts b/src/behaviors/BComputedAndWatch/types.ts index c99aaf1..2bdb8d5 100644 --- a/src/behaviors/BComputedAndWatch/types.ts +++ b/src/behaviors/BComputedAndWatch/types.ts @@ -5,25 +5,27 @@ import type { ComputedDependence } from "./initComputed"; export type InstanceCustomFields = { __pendingSetData__?: object | null; __storeConfig__?: () => Record unknown>; - __computedStatus__?: "初始化中" | "待更新" | "更新完毕"; + __computedStatus__?: "待更新" | "更新完毕"; __computedUpdater__: Func; - __computedConfig__?: () => Record; - __computedCache__?: ComputedCache; + __computedInitCache__?: () => ComputedCache; + __computedCache__: ComputedCache | undefined; __watchOldValue__?: WatchOldValue; __watchConfig__?: () => Record; __compLoadList__?: Func[]; + + __prePropertiesValue__: object | undefined; + __setDataFromInner__?: boolean; disposer: Record; }; export type Instance = (ComponentInstance | PageInstance) & InstanceCustomFields; -export type ComputedCache = Record< - string, - { - dependences: ComputedDependence[]; - method: Func; - value: unknown; - } ->; +export type ItemCache = { + dependences: ComputedDependence[]; + method: Func; + value: unknown; +}; + +export type ComputedCache = Record; export type WatchOldValue = Record; diff --git a/src/behaviors/BStore.ts b/src/behaviors/BStore.ts index f3fe483..b79a102 100644 --- a/src/behaviors/BStore.ts +++ b/src/behaviors/BStore.ts @@ -5,22 +5,17 @@ import { deleteProtoField } from "../utils/deleteProtoField"; import type { Instance } from "./BComputedAndWatch/types"; export const BStore = Behavior({ + // @ts-ignore definitionFilter(options: FinalOptionsOfComponent) { // 初始化store const storeConfig = options.store; if (!storeConfig) return; const { toJS } = require("mobx") as typeof mobx; for (const key in storeConfig) { - options.data ||= {}; - options.data[key] = toJS(storeConfig[key]()); // 把响应式数据配置保留在methods的__storeConfig__字段下带入到组件实例中(不用函数返回方式也可以,但不符合methods字段类型),后续再从原型上删除。 - options.methods ||= {}; - options.methods.__storeConfig__ = () => storeConfig; - - delete options.store; } }, lifetimes: { @@ -28,6 +23,8 @@ export const BStore = Behavior({ // 取出通过addStoreConfigToMethods函数带入的storeConfig const storeConfig = this.__storeConfig__?.(); if (!storeConfig) return; + deleteProtoField(this, "__storeConfig__"); + const { comparer, reaction, toJS } = require("mobx") as typeof mobx; this.disposer = {}; @@ -47,7 +44,6 @@ export const BStore = Behavior({ }, ); } - deleteProtoField(this, "__storeConfig__"); }, /* istanbul ignore next */ detached(this: Instance) { diff --git a/src/behaviors/BbeforeCreated.ts b/src/behaviors/BbeforeCreated.ts index 2a7a7a5..ba293f5 100644 --- a/src/behaviors/BbeforeCreated.ts +++ b/src/behaviors/BbeforeCreated.ts @@ -1,8 +1,11 @@ import type { FinalOptionsOfComponent } from "../api/DefineComponent/collectOptionsForComponent"; export const BBeforeCreate = Behavior({ - definitionFilter(options: FinalOptionsOfComponent) { - // 触发beforeCreate生命周期函数 + // @ts-ignore + definitionFilter( + options: Omit, + ) { + // 触发beforeCreate生命周期函数 options.lifetimes在之前被赋值过默认{}所以! const beforeCreateFunc = options.lifetimes!.beforeCreate; beforeCreateFunc && beforeCreateFunc(options); diff --git a/src/utils/InnerMarker.ts b/src/utils/InnerMarker.ts index dd441d3..216fb45 100644 --- a/src/utils/InnerMarker.ts +++ b/src/utils/InnerMarker.ts @@ -1,4 +1,3 @@ export const INNERMARKER = { - url: "__annil__" satisfies `_${string}`, // url默认传值Data字段 必须是内部字段,因为会加入到实例的data下。 - // defUrl: "/xx&xx", // 标记 组件默认的的url类型 + url: "__annil__", // url默认传值Data字段 }; diff --git a/src/utils/isEmptyObject.ts b/src/utils/isEmptyObject.ts index a8913b6..03a4c0f 100644 --- a/src/utils/isEmptyObject.ts +++ b/src/utils/isEmptyObject.ts @@ -1,7 +1,7 @@ /** * 判断一个值是否为空对象 `{}` */ -export function isEmptyObject(obj: unknown) { +export function isEmptyObject(obj: object) { if ( typeof obj !== "object" || obj === null || Array.isArray(obj) || obj instanceof Set || obj instanceof Map || obj instanceof WeakSet || obj instanceof WeakMap