@feng3d/reactivity 1.0.8 → 1.0.11

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/dist/index.js CHANGED
@@ -1,6 +1,25 @@
1
- class Reactivity {
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ var _a, _b;
5
+ const _Reactivity = class _Reactivity {
2
6
  constructor() {
3
- this._parents = /* @__PURE__ */ new Map();
7
+ /**
8
+ * @private
9
+ */
10
+ __publicField(this, "_value");
11
+ /**
12
+ * 父反应节点集合。
13
+ *
14
+ * 记录了哪些节点依赖了当前节点。
15
+ * 当当前节点值发生变化时,会通知所有父节点。
16
+ *
17
+ * Map 的 key 是父节点,value 是父节点的版本号。
18
+ * 版本号用于判断依赖关系是否过期。
19
+ *
20
+ * @private
21
+ */
22
+ __publicField(this, "_parents", /* @__PURE__ */ new Map());
4
23
  }
5
24
  /**
6
25
  * 获取当前节点值。
@@ -21,8 +40,8 @@ class Reactivity {
21
40
  * 如果当前没有活动的响应式节点,或者不应该跟踪依赖,则不会建立依赖关系。
22
41
  */
23
42
  track() {
24
- if (!Reactivity.activeReactivity || !_shouldTrack) return;
25
- const parent = Reactivity.activeReactivity;
43
+ if (!_Reactivity.activeReactivity || !_shouldTrack) return;
44
+ const parent = _Reactivity.activeReactivity;
26
45
  if (parent) {
27
46
  this._parents.set(parent, parent._version);
28
47
  }
@@ -47,7 +66,17 @@ class Reactivity {
47
66
  });
48
67
  this._parents.clear();
49
68
  }
50
- }
69
+ };
70
+ /**
71
+ * 当前正在执行的反应式节点。
72
+ *
73
+ * 用于在依赖收集过程中标识当前正在执行的节点。
74
+ * 当其他节点访问此节点的值时,会将其作为父节点。
75
+ *
76
+ * @internal
77
+ */
78
+ __publicField(_Reactivity, "activeReactivity");
79
+ let Reactivity = _Reactivity;
51
80
  function forceTrack(fn) {
52
81
  const preShouldTrack = _shouldTrack;
53
82
  _shouldTrack = true;
@@ -65,15 +94,13 @@ function noTrack(fn) {
65
94
  let _shouldTrack = true;
66
95
  function batch(dep, isRunning) {
67
96
  if (isRunning) {
68
- const index = _isRunedDeps.indexOf(dep);
69
- if (index !== -1) {
70
- console.warn("dep already in _isRunedDeps");
97
+ if (_isRunedDeps.indexOf(dep) !== -1) {
98
+ return;
71
99
  }
72
100
  _isRunedDeps.push(dep);
73
101
  } else {
74
- const index = _needEffectDeps.indexOf(dep);
75
- if (index !== -1) {
76
- console.warn("dep already in _needEffectDeps,存在多重依赖问题。可能是由于副作用中多次修改了同一个响应式对象。");
102
+ if (_needEffectDeps.indexOf(dep) !== -1) {
103
+ return;
77
104
  }
78
105
  _needEffectDeps.push(dep);
79
106
  }
@@ -86,6 +113,7 @@ function batchRun(fn) {
86
113
  }
87
114
  if (_isRunedDeps.length > 0) {
88
115
  _isRunedDeps.forEach((dep) => {
116
+ __DEV__ && console.assert(dep._isDirty === false, "dep.dirty === false");
89
117
  dep._children.forEach((version, node) => {
90
118
  node._parents.set(dep, dep._version);
91
119
  });
@@ -118,10 +146,48 @@ class ComputedReactivity extends Reactivity {
118
146
  */
119
147
  constructor(func) {
120
148
  super();
121
- this.__v_isRef = true;
122
- this._children = /* @__PURE__ */ new Map();
123
- this._isDirty = true;
124
- this._version = -1;
149
+ /**
150
+ * 标识这是一个 ref 对象。
151
+ *
152
+ * @internal
153
+ */
154
+ __publicField(this, "__v_isRef", true);
155
+ /**
156
+ * 计算函数。
157
+ *
158
+ * 用于计算属性值的函数,可以访问其他响应式数据。
159
+ * 当依赖发生变化时,会重新执行此函数。
160
+ */
161
+ __publicField(this, "_func");
162
+ /**
163
+ * 失效子节点集合。
164
+ *
165
+ * 记录所有依赖此计算属性的子节点。
166
+ * 当计算属性重新计算时,会通知这些子节点。
167
+ *
168
+ * @private
169
+ */
170
+ __publicField(this, "_children", /* @__PURE__ */ new Map());
171
+ /**
172
+ * 脏标记。
173
+ *
174
+ * 表示计算属性是否需要重新计算。
175
+ * 当依赖发生变化时,会设置此标记。
176
+ * 重新计算后会清除此标记。
177
+ *
178
+ * @private
179
+ */
180
+ __publicField(this, "_isDirty", true);
181
+ /**
182
+ * 版本号。
183
+ *
184
+ * 每次重新计算后自动递增。
185
+ * 用于判断子节点中的父节点引用是否过期。
186
+ * 当子节点发现父节点的版本号不匹配时,会重新建立依赖关系。
187
+ *
188
+ * @private
189
+ */
190
+ __publicField(this, "_version", -1);
125
191
  this._func = func;
126
192
  }
127
193
  /**
@@ -246,9 +312,9 @@ var TriggerOpTypes = /* @__PURE__ */ ((TriggerOpTypes2) => {
246
312
  TriggerOpTypes2["CLEAR"] = "clear";
247
313
  return TriggerOpTypes2;
248
314
  })(TriggerOpTypes || {});
249
- const ITERATE_KEY = Symbol("");
250
- const MAP_KEY_ITERATE_KEY = Symbol("");
251
- const ARRAY_ITERATE_KEY = Symbol("");
315
+ const ITERATE_KEY = Symbol(__DEV__ ? "Object iterate" : "");
316
+ const MAP_KEY_ITERATE_KEY = Symbol(__DEV__ ? "Map keys iterate" : "");
317
+ const ARRAY_ITERATE_KEY = Symbol(__DEV__ ? "Array iterate" : "");
252
318
  globalThis.__DEV__ ?? (globalThis.__DEV__ = true);
253
319
  const isObject = (val) => val !== null && typeof val === "object";
254
320
  const isArray = Array.isArray;
@@ -285,6 +351,9 @@ function toRaw(observed) {
285
351
  const raw = observed && observed[ReactiveFlags.RAW];
286
352
  return raw ? toRaw(raw) : observed;
287
353
  }
354
+ function warn(msg, ...args) {
355
+ console.warn(`[警告] ${msg}`, ...args);
356
+ }
288
357
  // @__NO_SIDE_EFFECTS__
289
358
  function makeMap(str) {
290
359
  const map = /* @__PURE__ */ Object.create(null);
@@ -298,12 +367,50 @@ class EffectScope {
298
367
  * @param detached 是否创建分离的作用域
299
368
  */
300
369
  constructor(detached = false) {
370
+ /**
371
+ * 作用域是否处于活动状态
372
+ * @internal
373
+ */
374
+ __publicField(this, "_active", true);
375
+ /**
376
+ * 跟踪 on 方法的调用次数,允许多次调用 on 方法
377
+ * @internal
378
+ */
379
+ __publicField(this, "_on", 0);
380
+ /**
381
+ * 存储当前作用域中的所有效果
382
+ * @internal
383
+ */
384
+ __publicField(this, "effects", []);
385
+ /**
386
+ * 存储清理函数
387
+ * @internal
388
+ */
389
+ __publicField(this, "cleanups", []);
390
+ /**
391
+ * 作用域是否被暂停
392
+ */
393
+ __publicField(this, "_isPaused", false);
394
+ /**
395
+ * 父作用域,仅由非分离的作用域分配
396
+ * @internal
397
+ */
398
+ __publicField(this, "parent");
399
+ /**
400
+ * 记录未分离的子作用域
401
+ * @internal
402
+ */
403
+ __publicField(this, "scopes");
404
+ /**
405
+ * 在父作用域的 scopes 数组中记录子作用域的索引,用于优化移除操作
406
+ * @internal
407
+ */
408
+ __publicField(this, "index");
409
+ /**
410
+ * 前一个作用域
411
+ */
412
+ __publicField(this, "prevScope");
301
413
  this.detached = detached;
302
- this._active = true;
303
- this._on = 0;
304
- this.effects = [];
305
- this.cleanups = [];
306
- this._isPaused = false;
307
414
  this.parent = activeEffectScope;
308
415
  if (!detached && activeEffectScope) {
309
416
  this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(
@@ -371,6 +478,8 @@ class EffectScope {
371
478
  } finally {
372
479
  activeEffectScope = currentEffectScope;
373
480
  }
481
+ } else if (__DEV__) {
482
+ warn(`无法运行已停用的 effect 作用域。`);
374
483
  }
375
484
  }
376
485
  /**
@@ -439,6 +548,10 @@ function getCurrentScope() {
439
548
  function onScopeDispose(fn, failSilently = false) {
440
549
  if (activeEffectScope) {
441
550
  activeEffectScope.cleanups.push(fn);
551
+ } else if (__DEV__ && !failSilently) {
552
+ warn(
553
+ `onScopeDispose() 在没有活动的 effect 作用域时被调用,无法关联。`
554
+ );
442
555
  }
443
556
  }
444
557
  function effect(fn) {
@@ -447,7 +560,12 @@ function effect(fn) {
447
560
  const _EffectReactivity = class _EffectReactivity extends ComputedReactivity {
448
561
  constructor(func) {
449
562
  super(func);
450
- this._isEnable = true;
563
+ /**
564
+ * 是否为启用, 默认为 true。
565
+ *
566
+ * 启用时,会立即执行函数。
567
+ */
568
+ __publicField(this, "_isEnable", true);
451
569
  if (activeEffectScope && activeEffectScope.active) {
452
570
  activeEffectScope.effects.push(this);
453
571
  }
@@ -511,7 +629,7 @@ const _EffectReactivity = class _EffectReactivity extends ComputedReactivity {
511
629
  }
512
630
  }
513
631
  };
514
- _EffectReactivity.pausedQueueEffects = /* @__PURE__ */ new WeakSet();
632
+ __publicField(_EffectReactivity, "pausedQueueEffects", /* @__PURE__ */ new WeakSet());
515
633
  let EffectReactivity = _EffectReactivity;
516
634
  function property(target, key) {
517
635
  let depsMap = PropertyReactivity._targetMap.get(target);
@@ -526,7 +644,21 @@ function property(target, key) {
526
644
  }
527
645
  return dep;
528
646
  }
529
- const _PropertyReactivity = class _PropertyReactivity extends Reactivity {
647
+ class PropertyReactivity extends Reactivity {
648
+ constructor(target, key) {
649
+ super();
650
+ __publicField(this, "_target");
651
+ __publicField(this, "_key");
652
+ this._target = target;
653
+ this._key = key;
654
+ if (target instanceof Map || target instanceof WeakMap) {
655
+ this._value = target.get(key);
656
+ } else if (target instanceof Set || target instanceof WeakSet) {
657
+ this._value = target.has(key);
658
+ } else {
659
+ this._value = target[key];
660
+ }
661
+ }
530
662
  /**
531
663
  * 获取当前节点值。
532
664
  *
@@ -546,18 +678,6 @@ const _PropertyReactivity = class _PropertyReactivity extends Reactivity {
546
678
  this.trigger();
547
679
  this._value = v;
548
680
  }
549
- constructor(target, key) {
550
- super();
551
- this._target = target;
552
- this._key = key;
553
- if (target instanceof Map || target instanceof WeakMap) {
554
- this._value = target.get(key);
555
- } else if (target instanceof Set || target instanceof WeakSet) {
556
- this._value = target.has(key);
557
- } else {
558
- this._value = target[key];
559
- }
560
- }
561
681
  triggerIfChanged() {
562
682
  }
563
683
  /**
@@ -641,9 +761,11 @@ const _PropertyReactivity = class _PropertyReactivity extends Reactivity {
641
761
  }
642
762
  });
643
763
  }
644
- };
645
- _PropertyReactivity._targetMap = /* @__PURE__ */ new WeakMap();
646
- let PropertyReactivity = _PropertyReactivity;
764
+ }
765
+ /**
766
+ * @private
767
+ */
768
+ __publicField(PropertyReactivity, "_targetMap", /* @__PURE__ */ new WeakMap());
647
769
  const arrayInstrumentations = {
648
770
  __proto__: null,
649
771
  /**
@@ -1124,7 +1246,6 @@ function noTracking(self, method, args = []) {
1124
1246
  );
1125
1247
  return res;
1126
1248
  }
1127
- var _a, _b;
1128
1249
  function ref(value) {
1129
1250
  if (isRef(value)) {
1130
1251
  return value;
@@ -1142,7 +1263,21 @@ class RefReactivity extends (_b = Reactivity, _a = ReactiveFlags.IS_REF, _b) {
1142
1263
  */
1143
1264
  constructor(value) {
1144
1265
  super();
1145
- this[_a] = true;
1266
+ /**
1267
+ * 标识这是一个 ref 对象。
1268
+ *
1269
+ * 用于 isRef 函数判断对象是否为引用。
1270
+ */
1271
+ __publicField(this, _a, true);
1272
+ /**
1273
+ * 原始值。
1274
+ *
1275
+ * 存储未经响应式处理的原始值。
1276
+ * 用于比较值是否发生变化。
1277
+ *
1278
+ * @private
1279
+ */
1280
+ __publicField(this, "_rawValue");
1146
1281
  this._rawValue = toRaw(value);
1147
1282
  this._value = toReactive(value);
1148
1283
  }
@@ -1263,6 +1398,7 @@ class MutableReactiveHandler extends BaseReactiveHandler {
1263
1398
  value,
1264
1399
  isRef(target) ? target : receiver
1265
1400
  );
1401
+ __DEV__ && console.assert(target === toRaw(receiver));
1266
1402
  if (target === toRaw(receiver)) {
1267
1403
  if (!hadKey) {
1268
1404
  PropertyReactivity.trigger(target, TriggerOpTypes.ADD, key, value);
@@ -1489,6 +1625,8 @@ function createInstrumentations() {
1489
1625
  if (!hadKey) {
1490
1626
  key = toRaw(key);
1491
1627
  hadKey = has.call(target, key);
1628
+ } else if (__DEV__) {
1629
+ checkIdentityKeys(target, has, key);
1492
1630
  }
1493
1631
  const oldValue = get.call(target, key);
1494
1632
  target.set(key, value);
@@ -1516,6 +1654,8 @@ function createInstrumentations() {
1516
1654
  if (!hadKey) {
1517
1655
  key = toRaw(key);
1518
1656
  hadKey = has.call(target, key);
1657
+ } else if (__DEV__) {
1658
+ checkIdentityKeys(target, has, key);
1519
1659
  }
1520
1660
  const oldValue = get ? get.call(target, key) : void 0;
1521
1661
  const result = target.delete(key);
@@ -1537,7 +1677,7 @@ function createInstrumentations() {
1537
1677
  clear() {
1538
1678
  const target = toRaw(this);
1539
1679
  const hadItems = target.size !== 0;
1540
- const oldTarget = void 0;
1680
+ const oldTarget = __DEV__ ? isMap(target) ? new Map(target) : new Set(target) : void 0;
1541
1681
  const result = target.clear();
1542
1682
  if (hadItems) {
1543
1683
  PropertyReactivity.trigger(
@@ -1592,6 +1732,15 @@ function createIterableMethod(method) {
1592
1732
  };
1593
1733
  };
1594
1734
  }
1735
+ function checkIdentityKeys(target, has, key) {
1736
+ const rawKey = toRaw(key);
1737
+ if (rawKey !== key && has.call(target, rawKey)) {
1738
+ const type = toRawType(target);
1739
+ warn(
1740
+ `响应式 ${type} 同时包含同一对象的原始版本和响应式版本${type === `Map` ? `作为键` : ``},这可能导致不一致。建议仅使用响应式版本。`
1741
+ );
1742
+ }
1743
+ }
1595
1744
  const getProto = (v) => Reflect.getPrototypeOf(v);
1596
1745
  function reactive(target) {
1597
1746
  if (!isObject(target)) {
@@ -1630,8 +1779,21 @@ function isProxy(value) {
1630
1779
  }
1631
1780
  class ReactiveObject {
1632
1781
  constructor() {
1633
- this._effectScope = new EffectScope();
1634
- this._destroyCallbacks = [];
1782
+ /**
1783
+ * 副作用作用域
1784
+ *
1785
+ * 用于管理所有副作用的生命周期:
1786
+ * - 收集所有通过 effect() 方法创建的副作用
1787
+ * - 在类销毁时自动停止所有副作用
1788
+ * - 防止副作用在类销毁后继续执行,避免内存泄漏
1789
+ *
1790
+ * 私有属性,外部无法直接访问,只能通过 effect() 方法使用
1791
+ */
1792
+ __publicField(this, "_effectScope", new EffectScope());
1793
+ /**
1794
+ * 销毁时需要执行的函数
1795
+ */
1796
+ __publicField(this, "_destroyCallbacks", []);
1635
1797
  }
1636
1798
  /**
1637
1799
  * 创建并运行副作用