@viewfly/core 3.0.0 → 3.0.1

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.
@@ -28,7 +28,7 @@ export declare class Component {
28
28
  props: Record<string, any>;
29
29
  readonly key?: Key;
30
30
  instance: ComponentInstance;
31
- changedSubComponents: Set<Component>;
31
+ changedSubComponents: Set<Component> | null;
32
32
  get dirty(): boolean;
33
33
  get changed(): boolean;
34
34
  /**
@@ -55,6 +55,7 @@ export declare class Component {
55
55
  rendered(): void;
56
56
  private invokeMountHooks;
57
57
  private invokeUpdatedHooks;
58
+ private getOrCreateRefEffects;
58
59
  }
59
60
  /**
60
61
  * 获取当前组件实例
package/dist/index.esm.js CHANGED
@@ -615,6 +615,15 @@ function cleanupEmptyEffects(target, type, key, effects, record, subscriber) {
615
615
  subscriber.delete(type);
616
616
  if (subscriber.size === 0) subscribers.delete(target);
617
617
  }
618
+ /** @internal 是否有订阅者监听 target 上某一追踪键(用于 computed 等按需刷新) */
619
+ function hasEffectSubscribers(target, type, key = unKnownKey) {
620
+ const subscriber = subscribers.get(target);
621
+ if (!subscriber) return false;
622
+ const record = subscriber.get(type);
623
+ if (!record) return false;
624
+ const effects = record.get(key);
625
+ return !!effects && effects.size > 0;
626
+ }
618
627
  function track(target, type, key = unKnownKey) {
619
628
  const dep = getDepContext();
620
629
  if (dep) {
@@ -1469,7 +1478,7 @@ var Component = class {
1469
1478
  this.props = props;
1470
1479
  this.key = key;
1471
1480
  this.instance = null;
1472
- this.changedSubComponents = /* @__PURE__ */ new Set();
1481
+ this.changedSubComponents = null;
1473
1482
  this.viewMetadata = null;
1474
1483
  this.unmountedCallbacks = null;
1475
1484
  this.mountCallbacks = null;
@@ -1480,7 +1489,7 @@ var Component = class {
1480
1489
  this.isFirstRendering = true;
1481
1490
  this.rawProps = props;
1482
1491
  this.props = createShallowReadonlyProxy({ ...props });
1483
- this.refEffects = /* @__PURE__ */ new Map();
1492
+ this.refEffects = null;
1484
1493
  this.listener = new Dep(() => {
1485
1494
  this.markAsDirtied();
1486
1495
  }, "sync");
@@ -1490,7 +1499,10 @@ var Component = class {
1490
1499
  this.markAsChanged();
1491
1500
  }
1492
1501
  markAsChanged(changedComponent) {
1493
- if (changedComponent) this.changedSubComponents.add(changedComponent);
1502
+ if (changedComponent) {
1503
+ if (!this.changedSubComponents) this.changedSubComponents = /* @__PURE__ */ new Set();
1504
+ this.changedSubComponents.add(changedComponent);
1505
+ }
1494
1506
  if (this._changed) return;
1495
1507
  this._changed = true;
1496
1508
  if (this.parentComponent) this.parentComponent.markAsChanged(this);
@@ -1501,8 +1513,13 @@ var Component = class {
1501
1513
  const isRenderFn = typeof render === "function";
1502
1514
  this.instance = isRenderFn ? { render } : render;
1503
1515
  onMounted(() => {
1504
- applyRefs(this.props.ref, this.instance, this.refEffects);
1516
+ const refs = this.props.ref;
1517
+ if (refs) {
1518
+ const refEffects = this.getOrCreateRefEffects();
1519
+ applyRefs(refs, this.instance, refEffects);
1520
+ }
1505
1521
  return () => {
1522
+ if (!this.refEffects) return;
1506
1523
  this.refEffects.forEach((fn) => {
1507
1524
  if (typeof fn === "function") fn();
1508
1525
  });
@@ -1519,7 +1536,10 @@ var Component = class {
1519
1536
  const oldProps = this.rawProps;
1520
1537
  this.rawProps = newProps;
1521
1538
  const newRefs = newProps.ref;
1522
- updateRefs(newRefs, this.instance, this.refEffects);
1539
+ if (oldProps.ref || newRefs) {
1540
+ const refEffects = this.getOrCreateRefEffects();
1541
+ updateRefs(newRefs, this.instance, refEffects);
1542
+ }
1523
1543
  comparePropsWithCallbacks(oldProps, newProps, (key) => {
1524
1544
  internalWrite(() => {
1525
1545
  Reflect.deleteProperty(oldProps, key);
@@ -1549,10 +1569,10 @@ var Component = class {
1549
1569
  if (this.unmountedCallbacks) this.unmountedCallbacks.forEach((fn) => {
1550
1570
  fn();
1551
1571
  });
1552
- this.parentComponent = this.updatedDestroyCallbacks = this.mountCallbacks = this.updatedCallbacks = this.unmountedCallbacks = null;
1572
+ this.parentComponent = this.changedSubComponents = this.refEffects = this.updatedDestroyCallbacks = this.mountCallbacks = this.updatedCallbacks = this.unmountedCallbacks = null;
1553
1573
  }
1554
1574
  rendered() {
1555
- this.changedSubComponents.clear();
1575
+ this.changedSubComponents?.clear();
1556
1576
  const is = this.isFirstRendering;
1557
1577
  this.isFirstRendering = false;
1558
1578
  this._dirty = this._changed = false;
@@ -1591,6 +1611,10 @@ var Component = class {
1591
1611
  this.updatedDestroyCallbacks = updatedDestroyCallbacks.length ? updatedDestroyCallbacks : null;
1592
1612
  }
1593
1613
  }
1614
+ getOrCreateRefEffects() {
1615
+ if (!this.refEffects) this.refEffects = /* @__PURE__ */ new Map();
1616
+ return this.refEffects;
1617
+ }
1594
1618
  };
1595
1619
  /**
1596
1620
  * 获取当前组件实例
@@ -1979,18 +2003,15 @@ function patchComponent(nativeRenderer, component, oldChildAtom, newAtom, contex
1979
2003
  const rawContext = context;
1980
2004
  const { computedContainer, contextContainer } = component.viewMetadata;
1981
2005
  popContainer();
1982
- if (portalContainer) if (portalContainer === context.contextContainer) {
1983
- if (portalContainer !== computedContainer) needMove = true;
1984
- } else {
2006
+ if (portalContainer) {
1985
2007
  if (portalContainer !== computedContainer) needMove = true;
1986
- context = {
2008
+ if (portalContainer !== context.contextContainer) context = {
1987
2009
  isParent: true,
1988
2010
  anchorNode: portalContainer,
1989
2011
  contextContainer: context.contextContainer,
1990
2012
  computedContainer: portalContainer
1991
2013
  };
1992
- }
1993
- else if (contextContainer !== context.contextContainer) needMove = true;
2014
+ } else if (contextContainer !== context.contextContainer) needMove = true;
1994
2015
  component.viewMetadata = {
1995
2016
  atom: newAtom,
1996
2017
  ...context
@@ -2018,9 +2039,8 @@ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
2018
2039
  }
2019
2040
  component.rendered();
2020
2041
  } else if (component.changed) {
2021
- component.changedSubComponents.forEach((child) => {
2022
- deepUpdateByComponentDirtyTree(nativeRenderer, child, needMove);
2023
- });
2042
+ const changedSubComponents = component.changedSubComponents;
2043
+ if (changedSubComponents) for (const child of changedSubComponents) deepUpdateByComponentDirtyTree(nativeRenderer, child, needMove);
2024
2044
  component.rendered();
2025
2045
  }
2026
2046
  }
@@ -2128,7 +2148,7 @@ function updateComponent(nativeRenderer, context, offset, needMove, newAtom, old
2128
2148
  ...context
2129
2149
  };
2130
2150
  newAtom.child = oldAtom.child;
2131
- const skipSubComponentDiff = !component.changedSubComponents.size;
2151
+ const skipSubComponentDiff = !component.changedSubComponents?.size;
2132
2152
  reuseComponentView(nativeRenderer, newAtom.child, context, needMove, skipSubComponentDiff);
2133
2153
  if (!skipSubComponentDiff) component.rendered();
2134
2154
  }
@@ -2457,7 +2477,10 @@ var RootComponent = class extends Component {
2457
2477
  }
2458
2478
  markAsChanged(changedComponent) {
2459
2479
  this._changed = true;
2460
- if (changedComponent) this.changedSubComponents.add(changedComponent);
2480
+ if (changedComponent) {
2481
+ if (!this.changedSubComponents) this.changedSubComponents = /* @__PURE__ */ new Set();
2482
+ this.changedSubComponents.add(changedComponent);
2483
+ }
2461
2484
  this.refresh();
2462
2485
  }
2463
2486
  };
@@ -2534,29 +2557,39 @@ function viewfly(config) {
2534
2557
  /**
2535
2558
  * 创建一个 computed,当依赖的值发生变化时,会重新计算值。
2536
2559
  * computed 会返回一个对象,对象的 value 属性是计算的值。
2560
+ *
2561
+ * 若重新计算的结果与缓存值 `Object.is` 相等,不会对访问该 computed 的订阅者触发更新,
2562
+ * 避免无关依赖抖动导致的下游副作用。
2563
+ *
2537
2564
  * @param getter 计算函数,用于计算值
2538
2565
  * @returns 一个对象,对象的 value 属性是计算的值
2539
2566
  */
2540
2567
  function computed(getter) {
2541
2568
  let cacheValue;
2569
+ let hasCache = false;
2542
2570
  let dirty = true;
2543
2571
  const target = { get value() {
2544
- if (dirty) {
2545
- dep.destroy();
2546
- pushDepContext(dep);
2547
- try {
2548
- cacheValue = getter();
2549
- dirty = false;
2550
- } finally {
2551
- popDepContext();
2552
- }
2553
- }
2572
+ if (dirty) flushComputed(false);
2554
2573
  return cacheValue;
2555
2574
  } };
2575
+ function flushComputed(notify) {
2576
+ dep.destroy();
2577
+ pushDepContext(dep);
2578
+ try {
2579
+ const newValue = getter();
2580
+ const changed = !hasCache || !Object.is(newValue, cacheValue);
2581
+ hasCache = true;
2582
+ cacheValue = newValue;
2583
+ dirty = false;
2584
+ if (notify && changed) trigger(target, TriggerOpTypes.Set, "value");
2585
+ } finally {
2586
+ popDepContext();
2587
+ }
2588
+ }
2556
2589
  const dep = new Dep(() => {
2557
2590
  if (!dirty) {
2558
2591
  dirty = true;
2559
- trigger(target, TriggerOpTypes.Set, "value");
2592
+ if (hasEffectSubscribers(target, TrackOpTypes.Get, "value")) flushComputed(true);
2560
2593
  }
2561
2594
  }, "sync");
2562
2595
  registryComponentDestroyCallback(() => {
@@ -2643,4 +2676,4 @@ function createSignal(state) {
2643
2676
  return signal;
2644
2677
  }
2645
2678
  //#endregion
2646
- export { ArrayReactiveHandler, Component, Dep, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Portal, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, applyMark, applyRefs, comparePropsWithCallbacks, computed, createContext, createContextProvider, createDynamicRef, createRef, createRenderer, createShallowReadonlyProxy, createSignal, defaultArrayReactiveHandler, defaultMapReactiveHandler, defaultObjectReactiveHandler, defaultSetReactiveHandler, defaultShallowArrayReactiveHandler, defaultShallowMapReactiveHandler, defaultShallowObjectReactiveHandler, defaultShallowSetReactiveHandler, flushReactiveEffectsSync, forwardRef, getCurrentInstance, getDepContext, getSetupContext, inject, internalWrite, isReactive, jsx, jsxs, makeError, nextTick, normalizeProvider, onMounted, onUnmounted, onUpdated, popDepContext, proxyToRawCache, pushDepContext, rawToProxyCache, reactive, readonlyProxyHandler, registryComponentDestroyCallback, shallowProxyToRawCache, shallowRawToProxyCache, shallowReactive, toRaw, track, trigger, updateRefs, viewfly, watch, watchEffect, withAnnotation, withMark };
2679
+ export { ArrayReactiveHandler, Component, Dep, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Portal, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, applyMark, applyRefs, comparePropsWithCallbacks, computed, createContext, createContextProvider, createDynamicRef, createRef, createRenderer, createShallowReadonlyProxy, createSignal, defaultArrayReactiveHandler, defaultMapReactiveHandler, defaultObjectReactiveHandler, defaultSetReactiveHandler, defaultShallowArrayReactiveHandler, defaultShallowMapReactiveHandler, defaultShallowObjectReactiveHandler, defaultShallowSetReactiveHandler, flushReactiveEffectsSync, forwardRef, getCurrentInstance, getDepContext, getSetupContext, hasEffectSubscribers, inject, internalWrite, isReactive, jsx, jsxs, makeError, nextTick, normalizeProvider, onMounted, onUnmounted, onUpdated, popDepContext, proxyToRawCache, pushDepContext, rawToProxyCache, reactive, readonlyProxyHandler, registryComponentDestroyCallback, shallowProxyToRawCache, shallowRawToProxyCache, shallowReactive, toRaw, track, trigger, updateRefs, viewfly, watch, watchEffect, withAnnotation, withMark };
package/dist/index.js CHANGED
@@ -616,6 +616,15 @@ function cleanupEmptyEffects(target, type, key, effects, record, subscriber) {
616
616
  subscriber.delete(type);
617
617
  if (subscriber.size === 0) subscribers.delete(target);
618
618
  }
619
+ /** @internal 是否有订阅者监听 target 上某一追踪键(用于 computed 等按需刷新) */
620
+ function hasEffectSubscribers(target, type, key = unKnownKey) {
621
+ const subscriber = subscribers.get(target);
622
+ if (!subscriber) return false;
623
+ const record = subscriber.get(type);
624
+ if (!record) return false;
625
+ const effects = record.get(key);
626
+ return !!effects && effects.size > 0;
627
+ }
619
628
  function track(target, type, key = unKnownKey) {
620
629
  const dep = getDepContext();
621
630
  if (dep) {
@@ -1470,7 +1479,7 @@ var Component = class {
1470
1479
  this.props = props;
1471
1480
  this.key = key;
1472
1481
  this.instance = null;
1473
- this.changedSubComponents = /* @__PURE__ */ new Set();
1482
+ this.changedSubComponents = null;
1474
1483
  this.viewMetadata = null;
1475
1484
  this.unmountedCallbacks = null;
1476
1485
  this.mountCallbacks = null;
@@ -1481,7 +1490,7 @@ var Component = class {
1481
1490
  this.isFirstRendering = true;
1482
1491
  this.rawProps = props;
1483
1492
  this.props = createShallowReadonlyProxy({ ...props });
1484
- this.refEffects = /* @__PURE__ */ new Map();
1493
+ this.refEffects = null;
1485
1494
  this.listener = new Dep(() => {
1486
1495
  this.markAsDirtied();
1487
1496
  }, "sync");
@@ -1491,7 +1500,10 @@ var Component = class {
1491
1500
  this.markAsChanged();
1492
1501
  }
1493
1502
  markAsChanged(changedComponent) {
1494
- if (changedComponent) this.changedSubComponents.add(changedComponent);
1503
+ if (changedComponent) {
1504
+ if (!this.changedSubComponents) this.changedSubComponents = /* @__PURE__ */ new Set();
1505
+ this.changedSubComponents.add(changedComponent);
1506
+ }
1495
1507
  if (this._changed) return;
1496
1508
  this._changed = true;
1497
1509
  if (this.parentComponent) this.parentComponent.markAsChanged(this);
@@ -1502,8 +1514,13 @@ var Component = class {
1502
1514
  const isRenderFn = typeof render === "function";
1503
1515
  this.instance = isRenderFn ? { render } : render;
1504
1516
  onMounted(() => {
1505
- applyRefs(this.props.ref, this.instance, this.refEffects);
1517
+ const refs = this.props.ref;
1518
+ if (refs) {
1519
+ const refEffects = this.getOrCreateRefEffects();
1520
+ applyRefs(refs, this.instance, refEffects);
1521
+ }
1506
1522
  return () => {
1523
+ if (!this.refEffects) return;
1507
1524
  this.refEffects.forEach((fn) => {
1508
1525
  if (typeof fn === "function") fn();
1509
1526
  });
@@ -1520,7 +1537,10 @@ var Component = class {
1520
1537
  const oldProps = this.rawProps;
1521
1538
  this.rawProps = newProps;
1522
1539
  const newRefs = newProps.ref;
1523
- updateRefs(newRefs, this.instance, this.refEffects);
1540
+ if (oldProps.ref || newRefs) {
1541
+ const refEffects = this.getOrCreateRefEffects();
1542
+ updateRefs(newRefs, this.instance, refEffects);
1543
+ }
1524
1544
  comparePropsWithCallbacks(oldProps, newProps, (key) => {
1525
1545
  internalWrite(() => {
1526
1546
  Reflect.deleteProperty(oldProps, key);
@@ -1550,10 +1570,10 @@ var Component = class {
1550
1570
  if (this.unmountedCallbacks) this.unmountedCallbacks.forEach((fn) => {
1551
1571
  fn();
1552
1572
  });
1553
- this.parentComponent = this.updatedDestroyCallbacks = this.mountCallbacks = this.updatedCallbacks = this.unmountedCallbacks = null;
1573
+ this.parentComponent = this.changedSubComponents = this.refEffects = this.updatedDestroyCallbacks = this.mountCallbacks = this.updatedCallbacks = this.unmountedCallbacks = null;
1554
1574
  }
1555
1575
  rendered() {
1556
- this.changedSubComponents.clear();
1576
+ this.changedSubComponents?.clear();
1557
1577
  const is = this.isFirstRendering;
1558
1578
  this.isFirstRendering = false;
1559
1579
  this._dirty = this._changed = false;
@@ -1592,6 +1612,10 @@ var Component = class {
1592
1612
  this.updatedDestroyCallbacks = updatedDestroyCallbacks.length ? updatedDestroyCallbacks : null;
1593
1613
  }
1594
1614
  }
1615
+ getOrCreateRefEffects() {
1616
+ if (!this.refEffects) this.refEffects = /* @__PURE__ */ new Map();
1617
+ return this.refEffects;
1618
+ }
1595
1619
  };
1596
1620
  /**
1597
1621
  * 获取当前组件实例
@@ -1980,18 +2004,15 @@ function patchComponent(nativeRenderer, component, oldChildAtom, newAtom, contex
1980
2004
  const rawContext = context;
1981
2005
  const { computedContainer, contextContainer } = component.viewMetadata;
1982
2006
  popContainer();
1983
- if (portalContainer) if (portalContainer === context.contextContainer) {
1984
- if (portalContainer !== computedContainer) needMove = true;
1985
- } else {
2007
+ if (portalContainer) {
1986
2008
  if (portalContainer !== computedContainer) needMove = true;
1987
- context = {
2009
+ if (portalContainer !== context.contextContainer) context = {
1988
2010
  isParent: true,
1989
2011
  anchorNode: portalContainer,
1990
2012
  contextContainer: context.contextContainer,
1991
2013
  computedContainer: portalContainer
1992
2014
  };
1993
- }
1994
- else if (contextContainer !== context.contextContainer) needMove = true;
2015
+ } else if (contextContainer !== context.contextContainer) needMove = true;
1995
2016
  component.viewMetadata = {
1996
2017
  atom: newAtom,
1997
2018
  ...context
@@ -2019,9 +2040,8 @@ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
2019
2040
  }
2020
2041
  component.rendered();
2021
2042
  } else if (component.changed) {
2022
- component.changedSubComponents.forEach((child) => {
2023
- deepUpdateByComponentDirtyTree(nativeRenderer, child, needMove);
2024
- });
2043
+ const changedSubComponents = component.changedSubComponents;
2044
+ if (changedSubComponents) for (const child of changedSubComponents) deepUpdateByComponentDirtyTree(nativeRenderer, child, needMove);
2025
2045
  component.rendered();
2026
2046
  }
2027
2047
  }
@@ -2129,7 +2149,7 @@ function updateComponent(nativeRenderer, context, offset, needMove, newAtom, old
2129
2149
  ...context
2130
2150
  };
2131
2151
  newAtom.child = oldAtom.child;
2132
- const skipSubComponentDiff = !component.changedSubComponents.size;
2152
+ const skipSubComponentDiff = !component.changedSubComponents?.size;
2133
2153
  reuseComponentView(nativeRenderer, newAtom.child, context, needMove, skipSubComponentDiff);
2134
2154
  if (!skipSubComponentDiff) component.rendered();
2135
2155
  }
@@ -2458,7 +2478,10 @@ var RootComponent = class extends Component {
2458
2478
  }
2459
2479
  markAsChanged(changedComponent) {
2460
2480
  this._changed = true;
2461
- if (changedComponent) this.changedSubComponents.add(changedComponent);
2481
+ if (changedComponent) {
2482
+ if (!this.changedSubComponents) this.changedSubComponents = /* @__PURE__ */ new Set();
2483
+ this.changedSubComponents.add(changedComponent);
2484
+ }
2462
2485
  this.refresh();
2463
2486
  }
2464
2487
  };
@@ -2535,29 +2558,39 @@ function viewfly(config) {
2535
2558
  /**
2536
2559
  * 创建一个 computed,当依赖的值发生变化时,会重新计算值。
2537
2560
  * computed 会返回一个对象,对象的 value 属性是计算的值。
2561
+ *
2562
+ * 若重新计算的结果与缓存值 `Object.is` 相等,不会对访问该 computed 的订阅者触发更新,
2563
+ * 避免无关依赖抖动导致的下游副作用。
2564
+ *
2538
2565
  * @param getter 计算函数,用于计算值
2539
2566
  * @returns 一个对象,对象的 value 属性是计算的值
2540
2567
  */
2541
2568
  function computed(getter) {
2542
2569
  let cacheValue;
2570
+ let hasCache = false;
2543
2571
  let dirty = true;
2544
2572
  const target = { get value() {
2545
- if (dirty) {
2546
- dep.destroy();
2547
- pushDepContext(dep);
2548
- try {
2549
- cacheValue = getter();
2550
- dirty = false;
2551
- } finally {
2552
- popDepContext();
2553
- }
2554
- }
2573
+ if (dirty) flushComputed(false);
2555
2574
  return cacheValue;
2556
2575
  } };
2576
+ function flushComputed(notify) {
2577
+ dep.destroy();
2578
+ pushDepContext(dep);
2579
+ try {
2580
+ const newValue = getter();
2581
+ const changed = !hasCache || !Object.is(newValue, cacheValue);
2582
+ hasCache = true;
2583
+ cacheValue = newValue;
2584
+ dirty = false;
2585
+ if (notify && changed) trigger(target, TriggerOpTypes.Set, "value");
2586
+ } finally {
2587
+ popDepContext();
2588
+ }
2589
+ }
2557
2590
  const dep = new Dep(() => {
2558
2591
  if (!dirty) {
2559
2592
  dirty = true;
2560
- trigger(target, TriggerOpTypes.Set, "value");
2593
+ if (hasEffectSubscribers(target, TrackOpTypes.Get, "value")) flushComputed(true);
2561
2594
  }
2562
2595
  }, "sync");
2563
2596
  registryComponentDestroyCallback(() => {
@@ -2696,6 +2729,7 @@ exports.forwardRef = forwardRef;
2696
2729
  exports.getCurrentInstance = getCurrentInstance;
2697
2730
  exports.getDepContext = getDepContext;
2698
2731
  exports.getSetupContext = getSetupContext;
2732
+ exports.hasEffectSubscribers = hasEffectSubscribers;
2699
2733
  exports.inject = inject;
2700
2734
  exports.internalWrite = internalWrite;
2701
2735
  exports.isReactive = isReactive;
@@ -4,6 +4,10 @@ export interface Computed<T> {
4
4
  /**
5
5
  * 创建一个 computed,当依赖的值发生变化时,会重新计算值。
6
6
  * computed 会返回一个对象,对象的 value 属性是计算的值。
7
+ *
8
+ * 若重新计算的结果与缓存值 `Object.is` 相等,不会对访问该 computed 的订阅者触发更新,
9
+ * 避免无关依赖抖动导致的下游副作用。
10
+ *
7
11
  * @param getter 计算函数,用于计算值
8
12
  * @returns 一个对象,对象的 value 属性是计算的值
9
13
  */
@@ -16,5 +16,7 @@ export declare enum TriggerOpTypes {
16
16
  Clear = "Clear",
17
17
  Iterate = "Iterate"
18
18
  }
19
+ /** @internal 是否有订阅者监听 target 上某一追踪键(用于 computed 等按需刷新) */
20
+ export declare function hasEffectSubscribers(target: object, type: TrackOpTypes, key?: unknown): boolean;
19
21
  export declare function track(target: object, type: TrackOpTypes, key?: unknown): void;
20
22
  export declare function trigger(target: object, type: TriggerOpTypes, key?: unknown): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viewfly/core",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "Viewfly is a simple and easy-to-use JavaScript framework with an intuitive development experience.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.esm.js",