@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.
- package/dist/base/component.d.ts +2 -1
- package/dist/index.esm.js +63 -30
- package/dist/index.js +63 -29
- package/dist/reactive/computed.d.ts +4 -0
- package/dist/reactive/effect.d.ts +2 -0
- package/package.json +1 -1
package/dist/base/component.d.ts
CHANGED
|
@@ -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 =
|
|
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 =
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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)
|
|
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
|
|
2022
|
-
|
|
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
|
|
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)
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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)
|
|
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
|
|
2023
|
-
|
|
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
|
|
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)
|
|
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
|
-
|
|
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