@feng3d/reactivity 1.0.7 → 1.0.9

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 (70) hide show
  1. package/dist/index.js +87 -0
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.umd.cjs +89 -2
  4. package/dist/index.umd.cjs.map +1 -1
  5. package/lib/ReactiveObject.d.ts +101 -0
  6. package/lib/ReactiveObject.d.ts.map +1 -0
  7. package/lib/batch.d.ts.map +1 -1
  8. package/lib/effectScope.d.ts.map +1 -1
  9. package/lib/index.d.ts +1 -0
  10. package/lib/index.d.ts.map +1 -1
  11. package/package.json +28 -20
  12. package/src/ReactiveObject.ts +131 -0
  13. package/src/batch.ts +12 -0
  14. package/src/collectionHandlers.ts +4 -4
  15. package/src/effectScope.ts +2 -3
  16. package/src/index.ts +1 -0
  17. package/src/shared/general.ts +1 -1
  18. package/dist/assets/RobotoMono-Medium-DVgDz_OO.woff2 +0 -0
  19. package/dist/assets/RobotoMono-Regular-BPoF81uy.woff2 +0 -0
  20. package/dist/assets/index-a2qCSG5V.css +0 -629
  21. package/dist/assets/index.html-Dyp3udP2.js +0 -200
  22. package/dist/assets/modulepreload-polyfill-DaKOjhqt.js +0 -37
  23. package/dist/assets/package-DuJynByc.js +0 -2539
  24. package/dist/assets/src//345/244/215/346/235/202/346/203/205/345/206/265/345/217/226/345/200/274/index.html-C3hbV3IR.js +0 -59
  25. package/dist/assets/src//346/225/260/347/273/204/index.html-CHK6WEhd.js +0 -43
  26. package/dist/docs/.nojekyll +0 -1
  27. package/dist/docs/assets/hierarchy.js +0 -1
  28. package/dist/docs/assets/highlight.css +0 -92
  29. package/dist/docs/assets/icons.js +0 -18
  30. package/dist/docs/assets/icons.svg +0 -1
  31. package/dist/docs/assets/main.js +0 -60
  32. package/dist/docs/assets/navigation.js +0 -1
  33. package/dist/docs/assets/search.js +0 -1
  34. package/dist/docs/assets/style.css +0 -1640
  35. package/dist/docs/classes/EffectScope.html +0 -40
  36. package/dist/docs/functions/batchRun.html +0 -15
  37. package/dist/docs/functions/computed.html +0 -5
  38. package/dist/docs/functions/effect.html +0 -11
  39. package/dist/docs/functions/effectScope.html +0 -5
  40. package/dist/docs/functions/forceTrack.html +0 -6
  41. package/dist/docs/functions/getCurrentScope.html +0 -4
  42. package/dist/docs/functions/isProxy.html +0 -5
  43. package/dist/docs/functions/isReactive.html +0 -5
  44. package/dist/docs/functions/isRef.html +0 -5
  45. package/dist/docs/functions/noTrack.html +0 -6
  46. package/dist/docs/functions/onScopeDispose.html +0 -6
  47. package/dist/docs/functions/reactive.html +0 -19
  48. package/dist/docs/functions/ref.html +0 -13
  49. package/dist/docs/functions/toRaw.html +0 -4
  50. package/dist/docs/hierarchy.html +0 -1
  51. package/dist/docs/index.html +0 -129
  52. package/dist/docs/interfaces/Computed.html +0 -9
  53. package/dist/docs/interfaces/Effect.html +0 -8
  54. package/dist/docs/interfaces/Ref.html +0 -9
  55. package/dist/docs/modules.html +0 -1
  56. package/dist/docs/types/Reactive.html +0 -3
  57. package/dist/docs/types/UnReadonly.html +0 -3
  58. package/dist/files/RobotoMono-Medium.woff2 +0 -0
  59. package/dist/files/RobotoMono-Regular.woff2 +0 -0
  60. package/dist/files/ic_code_black_24dp.svg +0 -4
  61. package/dist/files/ic_search_black_24dp.svg +0 -4
  62. package/dist/files/main.css +0 -629
  63. package/dist/files/thumbnails.svg +0 -7
  64. package/dist/files.json +0 -7
  65. package/dist/index.html +0 -84
  66. package/dist/screenshots//345/244/215/346/235/202/346/203/205/345/206/265/345/217/226/345/200/274.jpg +0 -0
  67. package/dist/screenshots//346/225/260/347/273/204.jpg +0 -0
  68. package/dist/src//345/244/215/346/235/202/346/203/205/345/206/265/345/217/226/345/200/274/index.html +0 -70
  69. package/dist/src//346/225/260/347/273/204/index.html +0 -65
  70. package/dist/tags.json +0 -2
@@ -0,0 +1,101 @@
1
+ import { Effect } from '@feng3d/reactivity';
2
+ /**
3
+ * 响应式类基类
4
+ *
5
+ * 提供响应式编程的基础功能,包括:
6
+ * 1. 提供副作用管理机制,自动管理副作用的生命周期
7
+ * 2. 在类销毁时自动清理所有副作用,防止内存泄漏
8
+ *
9
+ * 使用方式:
10
+ * ```typescript
11
+ * class MyClass extends ReactiveObject {
12
+ * constructor() {
13
+ * super();
14
+ *
15
+ * // 创建副作用,会自动管理生命周期
16
+ * this.effect(() => {
17
+ * ...
18
+ * });
19
+ * }
20
+ * }
21
+ * ```
22
+ */
23
+ export declare class ReactiveObject {
24
+ constructor();
25
+ /**
26
+ * 副作用作用域
27
+ *
28
+ * 用于管理所有副作用的生命周期:
29
+ * - 收集所有通过 effect() 方法创建的副作用
30
+ * - 在类销毁时自动停止所有副作用
31
+ * - 防止副作用在类销毁后继续执行,避免内存泄漏
32
+ *
33
+ * 私有属性,外部无法直接访问,只能通过 effect() 方法使用
34
+ */
35
+ private _effectScope;
36
+ /**
37
+ * 销毁时需要执行的函数
38
+ */
39
+ private _destroyCallbacks;
40
+ /**
41
+ * 创建并运行副作用
42
+ *
43
+ * 功能:
44
+ * 1. 将传入的函数包装为副作用
45
+ * 2. 自动收集副作用中访问的响应式属性作为依赖
46
+ * 3. 当依赖变化时自动重新执行副作用
47
+ * 4. 在类销毁时自动停止副作用
48
+ *
49
+ * 使用场景:
50
+ * - 监听属性变化并执行相应操作
51
+ * - 自动更新UI或重新计算派生状态
52
+ * - 执行清理或初始化逻辑
53
+ *
54
+ * @param fn 副作用函数,会在依赖变化时自动执行
55
+ *
56
+ * 使用示例:
57
+ * ```typescript
58
+ * this.effect(() => {
59
+ * // 访问响应式属性,建立依赖关系
60
+ * const value = reactive(this).someProperty;
61
+ *
62
+ * // 执行相应的逻辑
63
+ * this.updateUI(value);
64
+ * });
65
+ * ```
66
+ */
67
+ effect(fn: () => void): Effect;
68
+ /**
69
+ * 销毁时执行的函数
70
+ * @param callback 销毁时执行的函数
71
+ */
72
+ destroyCall(callback: () => void): void;
73
+ /**
74
+ * 销毁响应式类实例
75
+ *
76
+ * 执行清理操作:
77
+ * 1. 执行所有注册的清理函数
78
+ * 2. 停止所有副作用作用域,防止副作用继续执行
79
+ * 3. 清理引用,帮助垃圾回收,防止内存泄漏
80
+ *
81
+ * 重要:
82
+ * - 子类重写此方法时必须调用 super.destroy()
83
+ * - 确保在类实例不再使用时调用此方法
84
+ * - 调用后实例将无法再使用 effect() 方法
85
+ *
86
+ * 使用示例:
87
+ * ```typescript
88
+ * class MyClass extends ReactiveObject {
89
+ * destroy() {
90
+ * // 执行子类特定的清理逻辑
91
+ * this.cleanup();
92
+ *
93
+ * // 必须调用父类的destroy方法
94
+ * super.destroy();
95
+ * }
96
+ * }
97
+ * ```
98
+ */
99
+ destroy(): void;
100
+ }
101
+ //# sourceMappingURL=ReactiveObject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReactiveObject.d.ts","sourceRoot":"","sources":["../src/ReactiveObject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAuB,MAAM,oBAAoB,CAAC;AAEjE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,cAAc;;IAMvB;;;;;;;;;OASG;IACH,OAAO,CAAC,YAAY,CAAqB;IAEzC;;OAEG;IACH,OAAO,CAAC,iBAAiB,CAAsB;IAE/C;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI;IAYrB;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI;IAKhC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,OAAO;CAUV"}
@@ -1 +1 @@
1
- {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGhD;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,kBAAkB,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAUvE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CA+C1C"}
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGhD;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,kBAAkB,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAsBvE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CA+C1C"}
@@ -1 +1 @@
1
- {"version":3,"file":"effectScope.d.ts","sourceRoot":"","sources":["../src/effectScope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,UAAU,CAAC;AAGzD;;GAEG;AACH,eAAO,IAAI,iBAAiB,EAAE,WAAW,GAAG,SAAS,CAAC;AAEtD;;;;GAIG;AACH,qBAAa,WAAW;IAgDD,QAAQ;IA9C3B;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAQ;IACvB;;;OAGG;IACH,OAAO,CAAC,GAAG,CAAK;IAChB;;;OAGG;IACH,OAAO,EAAE,cAAc,EAAE,CAAM;IAC/B;;;OAGG;IACH,QAAQ,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE,CAAM;IAE9B;;OAEG;IACH,OAAO,CAAC,SAAS,CAAS;IAE1B;;;OAGG;IACH,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IAChC;;;OAGG;IACH,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IAClC;;;OAGG;IACH,OAAO,CAAC,KAAK,CAAqB;IAElC;;;OAGG;gBACgB,QAAQ,UAAQ;IAYnC;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAqBb;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAwBd;;;;OAIG;IACH,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS;IAuBlC;;OAEG;IACH,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC;;;;OAIG;IACH,EAAE,IAAI,IAAI;IASV;;;;OAIG;IACH,GAAG,IAAI,IAAI;IASX;;;;;OAKG;IACH,IAAI,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI;CA2CnC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,WAAW,CAG3D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,WAAW,GAAG,SAAS,CAGzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,YAAY,UAAQ,GAAG,IAAI,CAazE"}
1
+ {"version":3,"file":"effectScope.d.ts","sourceRoot":"","sources":["../src/effectScope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,UAAU,CAAC;AAGzD;;GAEG;AACH,eAAO,IAAI,iBAAiB,EAAE,WAAW,GAAG,SAAS,CAAC;AAEtD;;;;GAIG;AACH,qBAAa,WAAW;IAgDD,QAAQ;IA9C3B;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAQ;IACvB;;;OAGG;IACH,OAAO,CAAC,GAAG,CAAK;IAChB;;;OAGG;IACH,OAAO,EAAE,cAAc,EAAE,CAAM;IAC/B;;;OAGG;IACH,QAAQ,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE,CAAM;IAE9B;;OAEG;IACH,OAAO,CAAC,SAAS,CAAS;IAE1B;;;OAGG;IACH,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IAChC;;;OAGG;IACH,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IAClC;;;OAGG;IACH,OAAO,CAAC,KAAK,CAAqB;IAElC;;;OAGG;gBACgB,QAAQ,UAAQ;IAYnC;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAGpB;IAED;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAqBb;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAwBd;;;;OAIG;IACH,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS;IAuBlC;;OAEG;IACH,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC;;;;OAIG;IACH,EAAE,IAAI,IAAI;IASV;;;;OAIG;IACH,GAAG,IAAI,IAAI;IASX;;;;;OAKG;IACH,IAAI,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI;CA2CnC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,WAAW,CAG3D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,WAAW,GAAG,SAAS,CAGzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,YAAY,UAAQ,GAAG,IAAI,CAYzE"}
package/lib/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export { computed, type Computed } from './computed';
3
3
  export { effect, type Effect } from './effect';
4
4
  export { effectScope, EffectScope, getCurrentScope, onScopeDispose } from './effectScope';
5
5
  export { isProxy, isReactive, reactive, type Reactive, type UnReadonly } from './reactive';
6
+ export { ReactiveObject } from './ReactiveObject';
6
7
  export { forceTrack, noTrack } from './Reactivity';
7
8
  export { isRef, ref, type Ref } from './ref';
8
9
  export { toRaw } from './shared/general';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC"}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@feng3d/reactivity",
3
- "type": "module",
4
- "version": "1.0.7",
3
+ "version": "1.0.9",
5
4
  "description": "反应式,主要用于feng3d中的数据驱动。",
6
5
  "homepage": "https://feng3d.com/reactivity",
6
+ "author": "feng",
7
+ "license": "MIT",
8
+ "type": "module",
7
9
  "main": "./dist/index.umd.cjs",
8
10
  "types": "./lib/index.d.ts",
9
11
  "module": "./dist/index.js",
10
- "author": "feng",
11
- "license": "MIT",
12
12
  "exports": {
13
13
  ".": {
14
14
  "types": "./lib/index.d.ts",
@@ -17,28 +17,24 @@
17
17
  }
18
18
  },
19
19
  "scripts": {
20
- "dev": "cd examples && npm run dev",
21
- "clean": "rimraf \"{lib,dist,public}\"",
22
- "build": "vite build",
23
- "test": "vitest",
24
- "types": "tsc",
25
- "watch": "tsc -w",
20
+ "examples:dev": "cd examples && npm run dev",
21
+ "postdocs": "node scripts/postdocs.js && cd examples && vite build --outDir ../public",
22
+ "clean": "rimraf lib dist public",
23
+ "build": "vite build && tsc",
24
+ "watch": "concurrently \"vite build --watch\" \"tsc -w\" \"vitest\"",
25
+ "test": "vitest run",
26
26
  "lint": "eslint . --ext .js,.ts --max-warnings 0",
27
27
  "lintfix": "npm run lint -- --fix",
28
- "docs": "typedoc && cd examples && vite build --outDir ../public",
29
- "upload_oss": "npm run docs && feng3d-cli oss_upload_dir",
30
- "release": "npm run clean && npm run lint && npm run build && npm run docs && npm run types && npm publish",
28
+ "docs": "typedoc",
31
29
  "prepublishOnly": "node scripts/prepublish.js",
32
- "postpublish": "node scripts/postpublish.js"
30
+ "release": "npm run clean && npm run lint && npm test && npm run build && npm run docs && npm publish",
31
+ "postpublish": "node scripts/postpublish.js",
32
+ "prepare": "husky"
33
33
  },
34
34
  "repository": {
35
35
  "type": "git",
36
36
  "url": "https://github.com/feng3d-labs/reactivity.git"
37
37
  },
38
- "workspaces": [
39
- ".",
40
- "./examples"
41
- ],
42
38
  "publishConfig": {
43
39
  "access": "public"
44
40
  },
@@ -64,6 +60,18 @@
64
60
  "typescript": "5.8.3",
65
61
  "typescript-eslint": "^8.32.1",
66
62
  "vite": "^6.3.5",
67
- "vitest": "^3.1.3"
68
- }
63
+ "vitest": "^3.1.3",
64
+ "concurrently": "^9.1.2",
65
+ "husky": "^9.1.7",
66
+ "lint-staged": "^15.2.10"
67
+ },
68
+ "lint-staged": {
69
+ "*.{js,ts}": [
70
+ "eslint --fix --max-warnings 0"
71
+ ]
72
+ },
73
+ "workspaces": [
74
+ ".",
75
+ "./examples"
76
+ ]
69
77
  }
@@ -0,0 +1,131 @@
1
+ import { Effect, effect, EffectScope } from '@feng3d/reactivity';
2
+
3
+ /**
4
+ * 响应式类基类
5
+ *
6
+ * 提供响应式编程的基础功能,包括:
7
+ * 1. 提供副作用管理机制,自动管理副作用的生命周期
8
+ * 2. 在类销毁时自动清理所有副作用,防止内存泄漏
9
+ *
10
+ * 使用方式:
11
+ * ```typescript
12
+ * class MyClass extends ReactiveObject {
13
+ * constructor() {
14
+ * super();
15
+ *
16
+ * // 创建副作用,会自动管理生命周期
17
+ * this.effect(() => {
18
+ * ...
19
+ * });
20
+ * }
21
+ * }
22
+ * ```
23
+ */
24
+ export class ReactiveObject
25
+ {
26
+ constructor()
27
+ {
28
+ }
29
+
30
+ /**
31
+ * 副作用作用域
32
+ *
33
+ * 用于管理所有副作用的生命周期:
34
+ * - 收集所有通过 effect() 方法创建的副作用
35
+ * - 在类销毁时自动停止所有副作用
36
+ * - 防止副作用在类销毁后继续执行,避免内存泄漏
37
+ *
38
+ * 私有属性,外部无法直接访问,只能通过 effect() 方法使用
39
+ */
40
+ private _effectScope = new EffectScope();
41
+
42
+ /**
43
+ * 销毁时需要执行的函数
44
+ */
45
+ private _destroyCallbacks: (() => void)[] = [];
46
+
47
+ /**
48
+ * 创建并运行副作用
49
+ *
50
+ * 功能:
51
+ * 1. 将传入的函数包装为副作用
52
+ * 2. 自动收集副作用中访问的响应式属性作为依赖
53
+ * 3. 当依赖变化时自动重新执行副作用
54
+ * 4. 在类销毁时自动停止副作用
55
+ *
56
+ * 使用场景:
57
+ * - 监听属性变化并执行相应操作
58
+ * - 自动更新UI或重新计算派生状态
59
+ * - 执行清理或初始化逻辑
60
+ *
61
+ * @param fn 副作用函数,会在依赖变化时自动执行
62
+ *
63
+ * 使用示例:
64
+ * ```typescript
65
+ * this.effect(() => {
66
+ * // 访问响应式属性,建立依赖关系
67
+ * const value = reactive(this).someProperty;
68
+ *
69
+ * // 执行相应的逻辑
70
+ * this.updateUI(value);
71
+ * });
72
+ * ```
73
+ */
74
+ effect(fn: () => void)
75
+ {
76
+ let eff: Effect;
77
+
78
+ this._effectScope.run(() =>
79
+ {
80
+ eff = effect(fn);
81
+ });
82
+
83
+ return eff;
84
+ }
85
+
86
+ /**
87
+ * 销毁时执行的函数
88
+ * @param callback 销毁时执行的函数
89
+ */
90
+ destroyCall(callback: () => void)
91
+ {
92
+ this._destroyCallbacks.push(callback);
93
+ }
94
+
95
+ /**
96
+ * 销毁响应式类实例
97
+ *
98
+ * 执行清理操作:
99
+ * 1. 执行所有注册的清理函数
100
+ * 2. 停止所有副作用作用域,防止副作用继续执行
101
+ * 3. 清理引用,帮助垃圾回收,防止内存泄漏
102
+ *
103
+ * 重要:
104
+ * - 子类重写此方法时必须调用 super.destroy()
105
+ * - 确保在类实例不再使用时调用此方法
106
+ * - 调用后实例将无法再使用 effect() 方法
107
+ *
108
+ * 使用示例:
109
+ * ```typescript
110
+ * class MyClass extends ReactiveObject {
111
+ * destroy() {
112
+ * // 执行子类特定的清理逻辑
113
+ * this.cleanup();
114
+ *
115
+ * // 必须调用父类的destroy方法
116
+ * super.destroy();
117
+ * }
118
+ * }
119
+ * ```
120
+ */
121
+ destroy()
122
+ {
123
+ // 执行所有注册的清理函数
124
+ this._destroyCallbacks?.forEach((item) => item());
125
+ this._destroyCallbacks = null;
126
+
127
+ // 停止副作用作用域,这会自动停止所有通过 effect() 创建的副作用
128
+ this._effectScope?.stop();
129
+ this._effectScope = null;
130
+ }
131
+ }
package/src/batch.ts CHANGED
@@ -15,10 +15,22 @@ export function batch(dep: ComputedReactivity, isRunning: boolean): void
15
15
  {
16
16
  if (isRunning)
17
17
  {
18
+ // 如果依赖已经在队列中,直接返回,避免重复添加
19
+ if (_isRunedDeps.indexOf(dep) !== -1)
20
+ {
21
+ return;
22
+ }
23
+
18
24
  _isRunedDeps.push(dep);
19
25
  }
20
26
  else
21
27
  {
28
+ // 如果依赖已经在队列中,直接返回,避免重复添加
29
+ if (_needEffectDeps.indexOf(dep) !== -1)
30
+ {
31
+ return;
32
+ }
33
+
22
34
  _needEffectDeps.push(dep);
23
35
  }
24
36
  }
@@ -434,10 +434,10 @@ function checkIdentityKeys(
434
434
  const type = toRawType(target);
435
435
 
436
436
  warn(
437
- `Reactive ${type} contains both the raw and reactive ` +
438
- `versions of the same object${type === `Map` ? ` as keys` : ``}, ` +
439
- `which can lead to inconsistencies. ` +
440
- `It is recommended to use only the reactive version.`,
437
+ `响应式 ${type} 同时包含同一对象的原始版本和响应式版本` +
438
+ `${type === `Map` ? `作为键` : ``},` +
439
+ `这可能导致不一致。` +
440
+ `建议仅使用响应式版本。`,
441
441
  );
442
442
  }
443
443
  }
@@ -158,7 +158,7 @@ export class EffectScope
158
158
  }
159
159
  else if (__DEV__)
160
160
  {
161
- warn(`cannot run an inactive effect scope.`);
161
+ warn(`无法运行已停用的 effect 作用域。`);
162
162
  }
163
163
  }
164
164
 
@@ -287,8 +287,7 @@ export function onScopeDispose(fn: () => void, failSilently = false): void
287
287
  else if (__DEV__ && !failSilently)
288
288
  {
289
289
  warn(
290
- `onScopeDispose() is called when there is no active effect scope` +
291
- ` to be associated with.`,
290
+ `onScopeDispose() 在没有活动的 effect 作用域时被调用,无法关联。`,
292
291
  );
293
292
  }
294
293
  }
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ export { computed, type Computed } from './computed';
3
3
  export { effect, type Effect } from './effect';
4
4
  export { effectScope, EffectScope, getCurrentScope, onScopeDispose } from './effectScope';
5
5
  export { isProxy, isReactive, reactive, type Reactive, type UnReadonly } from './reactive';
6
+ export { ReactiveObject } from './ReactiveObject';
6
7
  export { forceTrack, noTrack } from './Reactivity';
7
8
  export { isRef, ref, type Ref } from './ref';
8
9
  export { toRaw } from './shared/general';
@@ -86,7 +86,7 @@ export function toRaw<T>(observed: T): T
86
86
 
87
87
  export function warn(msg: string, ...args: any[]): void
88
88
  {
89
- console.warn(`[Vue warn] ${msg}`, ...args);
89
+ console.warn(`[警告] ${msg}`, ...args);
90
90
  }
91
91
 
92
92
  /**