@feng3d/reactivity 0.0.1 → 1.0.3

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 (45) hide show
  1. package/README.md +124 -26
  2. package/dist/index.js +1018 -58
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.umd.cjs +1017 -57
  5. package/dist/index.umd.cjs.map +1 -1
  6. package/lib/Reactivity.d.ts +69 -0
  7. package/lib/Reactivity.d.ts.map +1 -0
  8. package/lib/arrayInstrumentations.d.ts +2 -0
  9. package/lib/arrayInstrumentations.d.ts.map +1 -0
  10. package/lib/baseHandlers.d.ts +5 -0
  11. package/lib/baseHandlers.d.ts.map +1 -0
  12. package/lib/batch.d.ts +23 -0
  13. package/lib/batch.d.ts.map +1 -0
  14. package/lib/collectionHandlers.d.ts +7 -0
  15. package/lib/collectionHandlers.d.ts.map +1 -0
  16. package/lib/computed.d.ts +94 -0
  17. package/lib/computed.d.ts.map +1 -0
  18. package/lib/effect.d.ts +52 -0
  19. package/lib/effect.d.ts.map +1 -0
  20. package/lib/index.d.ts +7 -18
  21. package/lib/index.d.ts.map +1 -1
  22. package/lib/property.d.ts +44 -0
  23. package/lib/property.d.ts.map +1 -0
  24. package/lib/reactive.d.ts +66 -0
  25. package/lib/reactive.d.ts.map +1 -0
  26. package/lib/ref.d.ts +41 -0
  27. package/lib/ref.d.ts.map +1 -0
  28. package/lib/shared/constants.d.ts +34 -0
  29. package/lib/shared/constants.d.ts.map +1 -0
  30. package/lib/shared/general.d.ts +36 -0
  31. package/lib/shared/general.d.ts.map +1 -0
  32. package/package.json +3 -2
  33. package/src/Reactivity.ts +126 -0
  34. package/src/arrayInstrumentations.ts +448 -0
  35. package/src/baseHandlers.ts +220 -0
  36. package/src/batch.ts +91 -0
  37. package/src/collectionHandlers.ts +298 -0
  38. package/src/computed.ts +201 -0
  39. package/src/effect.ts +108 -0
  40. package/src/index.ts +7 -200
  41. package/src/property.ts +223 -0
  42. package/src/reactive.ts +130 -0
  43. package/src/ref.ts +88 -0
  44. package/src/shared/constants.ts +41 -0
  45. package/src/shared/general.ts +109 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @feng3d/reactivity
2
2
 
3
- feng3d的响应式库。
3
+ feng3d的响应式库,使用方式以及API与@vue/reactivity基本保持一致。
4
4
 
5
5
  源码:https://gitee.com/feng3d/reactivity
6
6
 
@@ -15,47 +15,145 @@ https://feng3d.com/reactivity
15
15
  npm install @feng3d/reactivity
16
16
  ```
17
17
 
18
- ## 示例
18
+ ## 快速开始
19
19
 
20
- ### 监听对象属性的变化
20
+ ```ts
21
+ import { ref, computed } from "@feng3d/reactivity";
22
+
23
+ const a = ref(1);
24
+ const b = ref(2);
25
+ const c = computed(() => a.value + b.value);
26
+
27
+ console.log(c.value); // 3
28
+ a.value = 3;
29
+ console.log(c.value); // 5
21
30
  ```
22
- import { computed, ref } from "@feng3d/reactivity";
23
31
 
24
- const result = { time: undefined, values: [] };
32
+ ## 缘由
33
+ 在feng3d引擎中使用`@vue/reactivity`代替`@feng3d/watcher`来维护数据驱动功能时发现性能严重下降。
25
34
 
26
- const b = ref(2);
35
+ 为了解决这个问题,我重新实现了一个响应式库,并且在性能上进行了优化。
36
+
37
+ ### 问题示例
38
+
39
+ 示例: https://feng3d.com/reactivity/#复杂情况取值
27
40
 
28
- function 递归(depth = 10)
41
+ | 运行库 | 性能(ms) | 速度(x) |
42
+ | --- | --- | --- |
43
+ | @feng3d/reactivity | 2.8 | 286 |
44
+ | @vue/reactivity | 801 | 1 |
45
+
46
+ ### 测试代码
47
+ ```ts
48
+ 复杂情况取值(ref, computed, 10000);
49
+
50
+ export function 复杂情况取值(ref: <T>(value?: T) => { value: T }, computed: <T>(func: (oldValue?: T) => T) => { readonly value: T }, count: number)
29
51
  {
30
- if (depth <= 0) return computed(() =>
52
+ const result = { time: undefined, values: [] };
53
+
54
+ const b = ref(2);
55
+
56
+ function 递归(depth = 10)
31
57
  {
32
- return b.value
33
- }).value;
58
+ if (depth <= 0) return computed(() =>
59
+ {
60
+ return b.value
61
+ }).value;
62
+
63
+ return computed(() =>
64
+ {
65
+ return 递归(depth - 1) + 递归(depth - 2);
66
+ }).value;
67
+ }
68
+
69
+ const cb = computed(() =>
70
+ {
71
+ return 递归(16);
72
+ });
73
+
74
+ b.value++;
75
+ cb.value;
34
76
 
35
- return computed(() =>
77
+ const start = performance.now();
78
+ for (let i = 0; i < count; i++)
36
79
  {
37
- return 递归(depth - 1) + 递归(depth - 2);
38
- }).value;
80
+ ref(1).value++; // 添加此行代码将会导致 @vue/reactivity 版本的性能下降,而 @feng3d/reactivity 版本的性能保持不变
81
+
82
+ cb.value;
83
+ }
84
+ result.time = performance.now() - start;
85
+
86
+ result.values.push(cb.value);
87
+
88
+ return result;
39
89
  }
90
+ ```
91
+
92
+ ### 分析
93
+ @feng3d/reactivity自下而上的使用脏标记进行维护状态,当发生变化时只会冒泡一次到父节点,全局有变化时(ref(1).value++ 标记变化)并不会触发重新计算。
94
+ @vue/reactivity自上而下的使用版本号进行维护状态,当全局有变化时(ref(1).value++ 标记变化)每次取值时都会遍历整个树的子节点比对版本号判断是否需要重新计算。
95
+
96
+ ## 性能情况
97
+ ### 使用不同方式维护子节点
98
+
99
+ // 修改第一个元素 `arr[0].value++;`
100
+ | 方式 | 性能(ms) | 速度(x) | 隐患 |
101
+ | --- | --- | --- | --- |
102
+ | 失效子节点字典 | 126 | 8.8 | 当节点失效时无法完全清除子节点,并且无法保障检查节点的顺序,导致触发过时的依赖性能或许更差,但一般情况性能最佳。 |
103
+ | 全量子节点链表 | 679 | 1.6 | 无 |
104
+ | 全量子节点字典 | 1110 | 1 | 无 |
105
+ | @vue/reactivity | 216 | 5.1 | 无 |
106
+
107
+ // 修改最后一个元素 `arr[9999].value++`
108
+ | 方式 | 性能(ms) | 速度(x) | 隐患 |
109
+ | --- | --- | --- | --- |
110
+ | 失效子节点字典 | 125 | 9.68 | 当节点失效时无法完全清除子节点,并且无法保障检查节点的顺序,导致触发过时的依赖性能或许更差,但一般情况性能最佳。 |
111
+ | 全量子节点链表 | 730 | 1.65 | 无 |
112
+ | 全量子节点字典 | 1210 | 1 | 无 |
113
+ | @vue/reactivity | 253 | 4.78 | 无 |
114
+
115
+ ```ts
116
+ import { computed, ref } from "@feng3d/reactivity";
117
+
118
+ 数组取值(ref, computed, 1000)
40
119
 
41
- const cb = computed(() =>
120
+ export function 数组取值(ref: <T>(value?: T) => { value: T }, computed: <T>(func: (oldValue?: T) => T) => { readonly value: T },count: number)
42
121
  {
43
- return 递归(16);
44
- });
122
+ const result = { time: undefined, values: [] };
45
123
 
46
- const count = 10000;
124
+ const arr:{
125
+ value: number;
126
+ }[] = new Array(10000).fill(0).map(() => ref(0));
47
127
 
48
- b.value++;
49
- cb.value;
128
+ const cb = computed(() =>
129
+ {
130
+ return arr.reduce((prev, curr) => prev + curr.value, 0);
131
+ });
50
132
 
51
- const start = performance.now();
52
- for (let i = 0; i < count; i++)
53
- {
54
- ref(1).value++; // 添加此行代码将会导致 @vue/reactivity 版本的性能下降,而 @feng3d/reactivity 版本的性能保持不变
133
+ const start = performance.now();
134
+ for (let i = 0; i < count; i++)
135
+ {
136
+ // arr[0].value++; // 修改第一个元素
137
+ arr[9999].value++; // 修改最后一个元素
138
+ cb.value;
139
+ }
140
+ result.time = performance.now() - start;
55
141
 
56
- cb.value;
142
+ result.values.push(cb.value);
143
+
144
+ return result;
57
145
  }
58
- result.time = performance.now() - start;
59
146
 
60
- result.values.push(cb.value);
61
147
  ```
148
+
149
+ ## 为了库的简单易用性不支持以下内容
150
+ - markRaw
151
+ - shallowRef
152
+ - shallowReactive
153
+ - shallowReadonly
154
+ - readonly
155
+ - computed 中 setter
156
+ - __v_skip
157
+
158
+ ## 扩展
159
+ - 扩大被反应式的对象的类型范围,只有`Object.isExtensible`不通过的对象不被响应化。Float32Array等都允许被响应化。