@viewfly/core 1.0.0 → 1.0.2
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/bundles/index.d.ts +13 -11
- package/bundles/index.esm.js +145 -125
- package/bundles/index.js +145 -124
- package/package.json +2 -2
package/bundles/index.d.ts
CHANGED
|
@@ -195,6 +195,10 @@ interface Props {
|
|
|
195
195
|
children?: JSXNode | JSXNode[];
|
|
196
196
|
}
|
|
197
197
|
declare function Fragment(props: Props): () => JSXNode | JSXNode[];
|
|
198
|
+
interface ContextProps extends Props {
|
|
199
|
+
providers: Provider[];
|
|
200
|
+
}
|
|
201
|
+
declare function Context(props: ContextProps): () => JSXNode | JSXNode[];
|
|
198
202
|
type Key = number | string;
|
|
199
203
|
declare function jsx(type: string | ComponentSetup, props: Props & Record<string, any>, key?: Key): ViewFlyNode;
|
|
200
204
|
declare const jsxs: typeof jsx;
|
|
@@ -230,12 +234,14 @@ declare namespace JSX {
|
|
|
230
234
|
type ElementType = keyof IntrinsicElements | ComponentSetup;
|
|
231
235
|
interface Element extends ViewFlyNode {
|
|
232
236
|
}
|
|
233
|
-
interface
|
|
237
|
+
interface KeyedAttributes {
|
|
234
238
|
key?: Key;
|
|
239
|
+
}
|
|
240
|
+
interface IntrinsicAttributes extends KeyedAttributes {
|
|
235
241
|
ref?: any;
|
|
236
242
|
[key: string]: any;
|
|
237
243
|
}
|
|
238
|
-
interface RefAttributes<T> {
|
|
244
|
+
interface RefAttributes<T> extends KeyedAttributes {
|
|
239
245
|
ref?: DynamicRef<ExtractInstanceType<T>> | DynamicRef<ExtractInstanceType<T>>[];
|
|
240
246
|
}
|
|
241
247
|
interface ElementClass<P = any> extends ComponentInstance<P> {
|
|
@@ -274,7 +280,6 @@ declare class Component extends ReflectiveInjector {
|
|
|
274
280
|
props: Props;
|
|
275
281
|
readonly key?: Key | undefined;
|
|
276
282
|
instance: ComponentInstance<Props>;
|
|
277
|
-
template: JSXNode;
|
|
278
283
|
changedSubComponents: Set<Component>;
|
|
279
284
|
get dirty(): boolean;
|
|
280
285
|
get changed(): boolean;
|
|
@@ -292,14 +297,11 @@ declare class Component extends ReflectiveInjector {
|
|
|
292
297
|
constructor(parentComponent: Injector | null, type: ComponentSetup, props: Props, key?: Key | undefined);
|
|
293
298
|
markAsDirtied(): void;
|
|
294
299
|
markAsChanged(changedComponent?: Component): void;
|
|
295
|
-
render():
|
|
296
|
-
|
|
297
|
-
portalHost: NativeNode | undefined;
|
|
298
|
-
};
|
|
299
|
-
update(newProps: Record<string, any>): JSXNode;
|
|
300
|
+
render(update: (template: JSXNode, portalHost?: NativeNode) => void): void;
|
|
301
|
+
update(newProps: Record<string, any>, updateChildren: (jsxNode: JSXNode) => void, reuseChildren: (skipSubComponentDiff: boolean) => void): void;
|
|
300
302
|
provide<T>(providers: Provider<T> | Provider<T>[]): void;
|
|
301
|
-
rendered(): void;
|
|
302
303
|
destroy(): void;
|
|
304
|
+
rendered(): void;
|
|
303
305
|
private invokePropsChangedHooks;
|
|
304
306
|
private invokeMountHooks;
|
|
305
307
|
private invokeUpdatedHooks;
|
|
@@ -557,7 +559,7 @@ interface ComponentAtom {
|
|
|
557
559
|
}
|
|
558
560
|
type Atom = TextAtom | ElementAtom | ComponentAtom;
|
|
559
561
|
interface ComponentView {
|
|
560
|
-
atom:
|
|
562
|
+
atom: ComponentAtom;
|
|
561
563
|
host: NativeNode;
|
|
562
564
|
isParent: boolean;
|
|
563
565
|
rootHost: NativeNode;
|
|
@@ -590,4 +592,4 @@ interface Module {
|
|
|
590
592
|
}
|
|
591
593
|
declare function viewfly<T extends NativeNode>(config: Config): Application<T>;
|
|
592
594
|
|
|
593
|
-
export { type AbstractInstanceType, type AbstractProvider, type AbstractType, type Application, type Atom, type ClassNames, type ClassProvider, Component, type ComponentAnnotation, type ComponentInstance, type ComponentSetup, type ComponentView, type Config, type ConstructorProvider, DynamicRef, type ExistingProvider, type ExtractInstanceType, type ExtractValueType, type FactoryProvider, ForwardRef, Fragment, Inject, type InjectDecorator, InjectFlags, Injectable, type InjectableDecorator, type InjectableOptions, InjectionToken, Injector, JSX, type JSXNode, JSXNodeFactory, type Key, type LifeCycleCallback, type Module, type NativeNode, NativeRenderer, type NormalizedProvider, NullInjector, Optional, type OptionalDecorator, Prop, type PropDecorator, type Props, type PropsChangedCallback, type ProvideScope, type Provider, type RefListener, type ReflectiveDependency, ReflectiveInjector, RootComponent, Scope, Self, type SelfDecorator, type Signal, SkipSelf, type SkipSelfDecorator, type StaticProvider, StaticRef, THROW_IF_NOT_FOUND, Type, type TypeProvider, type ValueProvider, type ViewFlyNode, type WatchCallback, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|
|
595
|
+
export { type AbstractInstanceType, type AbstractProvider, type AbstractType, type Application, type Atom, type ClassNames, type ClassProvider, Component, type ComponentAnnotation, type ComponentInstance, type ComponentSetup, type ComponentView, type Config, type ConstructorProvider, Context, type ContextProps, DynamicRef, type ExistingProvider, type ExtractInstanceType, type ExtractValueType, type FactoryProvider, ForwardRef, Fragment, Inject, type InjectDecorator, InjectFlags, Injectable, type InjectableDecorator, type InjectableOptions, InjectionToken, Injector, JSX, type JSXNode, JSXNodeFactory, type Key, type LifeCycleCallback, type Module, type NativeNode, NativeRenderer, type NormalizedProvider, NullInjector, Optional, type OptionalDecorator, Prop, type PropDecorator, type Props, type PropsChangedCallback, type ProvideScope, type Provider, type RefListener, type ReflectiveDependency, ReflectiveInjector, RootComponent, Scope, Self, type SelfDecorator, type Signal, SkipSelf, type SkipSelfDecorator, type StaticProvider, StaticRef, THROW_IF_NOT_FOUND, Type, type TypeProvider, type ValueProvider, type ViewFlyNode, type WatchCallback, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|
package/bundles/index.esm.js
CHANGED
|
@@ -692,7 +692,7 @@ class Component extends ReflectiveInjector {
|
|
|
692
692
|
this.parentComponent.markAsChanged(this);
|
|
693
693
|
}
|
|
694
694
|
}
|
|
695
|
-
render() {
|
|
695
|
+
render(update) {
|
|
696
696
|
const self = this;
|
|
697
697
|
const proxiesProps = new Proxy(this.props, {
|
|
698
698
|
get(_, key) {
|
|
@@ -734,19 +734,22 @@ class Component extends ReflectiveInjector {
|
|
|
734
734
|
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
735
735
|
this.markAsDirtied();
|
|
736
736
|
});
|
|
737
|
-
this.
|
|
738
|
-
|
|
739
|
-
template: template,
|
|
740
|
-
portalHost: this.instance.$portalHost
|
|
741
|
-
};
|
|
737
|
+
update(template, this.instance.$portalHost);
|
|
738
|
+
this.rendered();
|
|
742
739
|
}
|
|
743
|
-
update(newProps) {
|
|
740
|
+
update(newProps, updateChildren, reuseChildren) {
|
|
744
741
|
const oldProps = this.props;
|
|
745
742
|
if (newProps !== oldProps) {
|
|
746
743
|
const { add, remove, replace } = getObjectChanges(newProps, oldProps);
|
|
747
744
|
if (add.length || remove.length || replace.length) {
|
|
748
745
|
this.invokePropsChangedHooks(newProps);
|
|
749
746
|
}
|
|
747
|
+
else if (!this.dirty) {
|
|
748
|
+
this.props = newProps;
|
|
749
|
+
reuseChildren(false);
|
|
750
|
+
this.rendered();
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
750
753
|
const newRefs = toRefs(newProps.ref);
|
|
751
754
|
if (this.refs) {
|
|
752
755
|
for (const oldRef of this.refs) {
|
|
@@ -764,39 +767,25 @@ class Component extends ReflectiveInjector {
|
|
|
764
767
|
}
|
|
765
768
|
if (typeof this.instance.$useMemo === 'function') {
|
|
766
769
|
if (this.instance.$useMemo(newProps, oldProps)) {
|
|
767
|
-
|
|
770
|
+
reuseChildren(true);
|
|
771
|
+
this.rendered();
|
|
772
|
+
return;
|
|
768
773
|
}
|
|
769
774
|
}
|
|
770
775
|
this.unWatch();
|
|
771
776
|
signalDepsStack.push([]);
|
|
772
|
-
|
|
777
|
+
const template = this.instance.$render();
|
|
773
778
|
const deps = signalDepsStack.pop();
|
|
774
779
|
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
775
780
|
this.markAsDirtied();
|
|
776
781
|
});
|
|
777
|
-
|
|
782
|
+
updateChildren(template);
|
|
783
|
+
this.rendered();
|
|
778
784
|
}
|
|
779
785
|
provide(providers) {
|
|
780
786
|
providers = Array.isArray(providers) ? providers : [providers];
|
|
781
787
|
this.normalizedProviders.unshift(...providers.map(i => normalizeProvider(i)));
|
|
782
788
|
}
|
|
783
|
-
rendered() {
|
|
784
|
-
this.changedSubComponents.clear();
|
|
785
|
-
const is = this.isFirstRendering;
|
|
786
|
-
this.isFirstRendering = false;
|
|
787
|
-
this._dirty = this._changed = false;
|
|
788
|
-
this.invokeUpdatedHooks();
|
|
789
|
-
if (is) {
|
|
790
|
-
this.invokeMountHooks();
|
|
791
|
-
}
|
|
792
|
-
if (this.changed) {
|
|
793
|
-
Promise.resolve().then(() => {
|
|
794
|
-
if (this.parentComponent instanceof Component) {
|
|
795
|
-
this.parentComponent.markAsChanged(this);
|
|
796
|
-
}
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
789
|
destroy() {
|
|
801
790
|
var _a, _b, _c;
|
|
802
791
|
this.unWatch();
|
|
@@ -816,6 +805,23 @@ class Component extends ReflectiveInjector {
|
|
|
816
805
|
this.propsChangedCallbacks =
|
|
817
806
|
this.unmountedCallbacks = null;
|
|
818
807
|
}
|
|
808
|
+
rendered() {
|
|
809
|
+
this.changedSubComponents.clear();
|
|
810
|
+
const is = this.isFirstRendering;
|
|
811
|
+
this.isFirstRendering = false;
|
|
812
|
+
this._dirty = this._changed = false;
|
|
813
|
+
this.invokeUpdatedHooks();
|
|
814
|
+
if (is) {
|
|
815
|
+
this.invokeMountHooks();
|
|
816
|
+
}
|
|
817
|
+
if (this.changed) {
|
|
818
|
+
Promise.resolve().then(() => {
|
|
819
|
+
if (this.parentComponent instanceof Component) {
|
|
820
|
+
this.parentComponent.markAsChanged(this);
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
}
|
|
819
825
|
invokePropsChangedHooks(newProps) {
|
|
820
826
|
const oldProps = this.props;
|
|
821
827
|
this.props = newProps;
|
|
@@ -1259,6 +1265,13 @@ function Fragment(props) {
|
|
|
1259
1265
|
return props.children;
|
|
1260
1266
|
};
|
|
1261
1267
|
}
|
|
1268
|
+
function Context(props) {
|
|
1269
|
+
const instance = getCurrentInstance();
|
|
1270
|
+
instance.provide(props.providers);
|
|
1271
|
+
return () => {
|
|
1272
|
+
return props.children;
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1262
1275
|
function jsx(type, props, key) {
|
|
1263
1276
|
return JSXNodeFactory.createNode(type, props, key);
|
|
1264
1277
|
}
|
|
@@ -1304,7 +1317,7 @@ function createRenderer(component, nativeRenderer) {
|
|
|
1304
1317
|
});
|
|
1305
1318
|
}
|
|
1306
1319
|
else {
|
|
1307
|
-
updateView(nativeRenderer, component);
|
|
1320
|
+
updateView(nativeRenderer, component, false);
|
|
1308
1321
|
}
|
|
1309
1322
|
};
|
|
1310
1323
|
}
|
|
@@ -1323,46 +1336,43 @@ function buildView(nativeRenderer, parentComponent, atom, context) {
|
|
|
1323
1336
|
}
|
|
1324
1337
|
}
|
|
1325
1338
|
function buildElementChildren(atom, nativeRenderer, parentComponent, context) {
|
|
1326
|
-
const childContext = {
|
|
1327
|
-
isParent: true,
|
|
1328
|
-
host: atom.nativeNode,
|
|
1329
|
-
rootHost: context.rootHost
|
|
1330
|
-
};
|
|
1331
1339
|
let child = atom.child;
|
|
1332
1340
|
while (child) {
|
|
1333
|
-
buildView(nativeRenderer, parentComponent, child,
|
|
1341
|
+
buildView(nativeRenderer, parentComponent, child, context);
|
|
1334
1342
|
child = child.sibling;
|
|
1335
1343
|
}
|
|
1336
1344
|
}
|
|
1337
|
-
function updateView(nativeRenderer, component) {
|
|
1345
|
+
function updateView(nativeRenderer, component, needMove) {
|
|
1338
1346
|
if (component.dirty) {
|
|
1339
|
-
|
|
1340
|
-
component
|
|
1347
|
+
const { atom, host, isParent, rootHost } = componentViewCache.get(component);
|
|
1348
|
+
applyChanges(nativeRenderer, component, atom, {
|
|
1349
|
+
host,
|
|
1350
|
+
isParent,
|
|
1351
|
+
rootHost
|
|
1352
|
+
}, needMove);
|
|
1341
1353
|
}
|
|
1342
1354
|
else if (component.changed) {
|
|
1343
1355
|
component.changedSubComponents.forEach(child => {
|
|
1344
|
-
updateView(nativeRenderer, child);
|
|
1356
|
+
updateView(nativeRenderer, child, needMove);
|
|
1345
1357
|
});
|
|
1346
1358
|
component.rendered();
|
|
1347
1359
|
}
|
|
1348
1360
|
}
|
|
1349
|
-
function applyChanges(nativeRenderer, component) {
|
|
1350
|
-
const { atom, host, isParent, rootHost } = componentViewCache.get(component);
|
|
1361
|
+
function applyChanges(nativeRenderer, component, atom, context, needMove) {
|
|
1351
1362
|
const diffAtom = atom.child;
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
}
|
|
1363
|
+
component.update(component.props, newTemplate => {
|
|
1364
|
+
atom.child = createChildChain(newTemplate, atom.isSvg);
|
|
1365
|
+
diff(nativeRenderer, component, atom.child, diffAtom, context, needMove);
|
|
1366
|
+
const next = atom.sibling;
|
|
1367
|
+
if (next && next.jsxNode instanceof Component) {
|
|
1368
|
+
const view = componentViewCache.get(next.jsxNode);
|
|
1369
|
+
view.host = context.host;
|
|
1370
|
+
view.isParent = context.isParent;
|
|
1371
|
+
}
|
|
1372
|
+
}, () => {
|
|
1373
|
+
// console.log(skipSubComponentDiff, '----')
|
|
1374
|
+
//
|
|
1375
|
+
});
|
|
1366
1376
|
}
|
|
1367
1377
|
function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
|
|
1368
1378
|
const commits = [];
|
|
@@ -1447,54 +1457,60 @@ function updateElement(newAtom, oldAtom, nativeRenderer, context, parentComponen
|
|
|
1447
1457
|
}
|
|
1448
1458
|
context.host = newAtom.nativeNode;
|
|
1449
1459
|
context.isParent = false;
|
|
1450
|
-
updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent,
|
|
1460
|
+
updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
|
|
1461
|
+
host: newAtom.nativeNode,
|
|
1462
|
+
isParent: true,
|
|
1463
|
+
rootHost: context.rootHost
|
|
1464
|
+
});
|
|
1451
1465
|
};
|
|
1452
1466
|
}
|
|
1453
1467
|
function updateComponent(newAtom, reusedAtom, nativeRenderer, context) {
|
|
1454
1468
|
return function (offset, needMove) {
|
|
1455
1469
|
const component = reusedAtom.jsxNode;
|
|
1456
1470
|
const newProps = newAtom.jsxNode.props;
|
|
1457
|
-
const oldTemplate = component.template;
|
|
1458
|
-
const newTemplate = component.update(newProps);
|
|
1459
1471
|
const portalHost = component.instance.$portalHost;
|
|
1460
1472
|
context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
|
|
1461
1473
|
componentViewCache.set(component, Object.assign({ atom: newAtom }, context));
|
|
1462
1474
|
newAtom.jsxNode = component;
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
component.rendered();
|
|
1467
|
-
return;
|
|
1468
|
-
}
|
|
1469
|
-
if (newTemplate) {
|
|
1470
|
-
newAtom.child = createChildChain(newTemplate, newAtom.isSvg);
|
|
1471
|
-
}
|
|
1472
|
-
if (newAtom.child) {
|
|
1473
|
-
diff(nativeRenderer, component, newAtom.child, reusedAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index);
|
|
1474
|
-
}
|
|
1475
|
-
else if (reusedAtom.child) {
|
|
1476
|
-
let atom = reusedAtom.child;
|
|
1477
|
-
while (atom) {
|
|
1478
|
-
cleanView(nativeRenderer, atom, true);
|
|
1479
|
-
atom = atom.sibling;
|
|
1475
|
+
component.update(newProps, newTemplate => {
|
|
1476
|
+
if (newTemplate) {
|
|
1477
|
+
newAtom.child = createChildChain(newTemplate, newAtom.isSvg);
|
|
1480
1478
|
}
|
|
1481
|
-
|
|
1482
|
-
|
|
1479
|
+
if (newAtom.child) {
|
|
1480
|
+
diff(nativeRenderer, component, newAtom.child, reusedAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index);
|
|
1481
|
+
}
|
|
1482
|
+
else if (reusedAtom.child) {
|
|
1483
|
+
let atom = reusedAtom.child;
|
|
1484
|
+
while (atom) {
|
|
1485
|
+
cleanView(nativeRenderer, atom, true);
|
|
1486
|
+
atom = atom.sibling;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
}, (skipSubComponentDiff) => {
|
|
1490
|
+
newAtom.child = reusedAtom.child;
|
|
1491
|
+
reuseComponentView(nativeRenderer, newAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index, skipSubComponentDiff);
|
|
1492
|
+
});
|
|
1483
1493
|
};
|
|
1484
1494
|
}
|
|
1485
|
-
function reuseComponentView(nativeRenderer, child, context, moveView) {
|
|
1495
|
+
function reuseComponentView(nativeRenderer, child, context, moveView, skipSubComponentDiff) {
|
|
1486
1496
|
const updateContext = (atom) => {
|
|
1487
1497
|
if (atom.jsxNode instanceof Component) {
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1498
|
+
if (skipSubComponentDiff || !moveView) {
|
|
1499
|
+
let child = atom.child;
|
|
1500
|
+
while (child) {
|
|
1501
|
+
updateContext(child);
|
|
1502
|
+
child = child.sibling;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
applyChanges(nativeRenderer, atom.jsxNode, atom, context, true);
|
|
1492
1507
|
}
|
|
1493
1508
|
}
|
|
1494
1509
|
else {
|
|
1495
1510
|
if (moveView) {
|
|
1496
1511
|
insertNode(nativeRenderer, atom, context);
|
|
1497
1512
|
}
|
|
1513
|
+
reuseElementChildrenView(nativeRenderer, atom);
|
|
1498
1514
|
context.isParent = false;
|
|
1499
1515
|
context.host = atom.nativeNode;
|
|
1500
1516
|
}
|
|
@@ -1504,6 +1520,18 @@ function reuseComponentView(nativeRenderer, child, context, moveView) {
|
|
|
1504
1520
|
child = child.sibling;
|
|
1505
1521
|
}
|
|
1506
1522
|
}
|
|
1523
|
+
function reuseElementChildrenView(nativeRenderer, atom, context, skipSubComponentDiff) {
|
|
1524
|
+
let child = atom.child;
|
|
1525
|
+
while (child) {
|
|
1526
|
+
if (child.jsxNode instanceof Component) {
|
|
1527
|
+
updateView(nativeRenderer, child.jsxNode, false);
|
|
1528
|
+
}
|
|
1529
|
+
else {
|
|
1530
|
+
reuseElementChildrenView(nativeRenderer, child);
|
|
1531
|
+
}
|
|
1532
|
+
child = child.sibling;
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1507
1535
|
function cleanElementChildren(atom, nativeRenderer) {
|
|
1508
1536
|
let child = atom.child;
|
|
1509
1537
|
nativeRenderer.cleanChildren(atom.nativeNode, atom.isSvg);
|
|
@@ -1536,16 +1564,16 @@ function cleanView(nativeRenderer, atom, needClean) {
|
|
|
1536
1564
|
}
|
|
1537
1565
|
}
|
|
1538
1566
|
function componentRender(nativeRenderer, component, from, context) {
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1567
|
+
component.render((template, portalHost) => {
|
|
1568
|
+
from.child = createChildChain(template, from.isSvg);
|
|
1569
|
+
context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
|
|
1570
|
+
componentViewCache.set(component, Object.assign({ atom: from }, context));
|
|
1571
|
+
let child = from.child;
|
|
1572
|
+
while (child) {
|
|
1573
|
+
buildView(nativeRenderer, component, child, context);
|
|
1574
|
+
child = child.sibling;
|
|
1575
|
+
}
|
|
1576
|
+
});
|
|
1549
1577
|
}
|
|
1550
1578
|
function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, isSvg, key) {
|
|
1551
1579
|
const atom = {
|
|
@@ -1648,7 +1676,11 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
|
|
|
1648
1676
|
}
|
|
1649
1677
|
atom.nativeNode = nativeNode;
|
|
1650
1678
|
insertNode(nativeRenderer, atom, context);
|
|
1651
|
-
buildElementChildren(atom, nativeRenderer, parentComponent,
|
|
1679
|
+
buildElementChildren(atom, nativeRenderer, parentComponent, {
|
|
1680
|
+
isParent: true,
|
|
1681
|
+
host: nativeNode,
|
|
1682
|
+
rootHost: context.rootHost
|
|
1683
|
+
});
|
|
1652
1684
|
context.host = nativeNode;
|
|
1653
1685
|
context.isParent = false;
|
|
1654
1686
|
applyRefs(bindingRefs, nativeNode, true);
|
|
@@ -1666,14 +1698,18 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1666
1698
|
const nativeNode = newAtom.nativeNode;
|
|
1667
1699
|
const oldVNode = oldAtom.jsxNode;
|
|
1668
1700
|
if (newVNode === oldVNode) {
|
|
1669
|
-
|
|
1701
|
+
newAtom.child = oldAtom.child;
|
|
1702
|
+
reuseElementChildrenView(nativeRenderer, newAtom);
|
|
1670
1703
|
return;
|
|
1671
1704
|
}
|
|
1672
1705
|
const changes = getObjectChanges(newVNode.props, oldVNode.props);
|
|
1673
1706
|
let unBindRefs;
|
|
1674
1707
|
let bindRefs;
|
|
1708
|
+
let updatedChildren = false;
|
|
1675
1709
|
for (const [key, value] of changes.remove) {
|
|
1676
1710
|
if (key === 'children') {
|
|
1711
|
+
updatedChildren = true;
|
|
1712
|
+
cleanElementChildren(oldAtom, nativeRenderer);
|
|
1677
1713
|
continue;
|
|
1678
1714
|
}
|
|
1679
1715
|
if (key === 'class') {
|
|
@@ -1700,6 +1736,14 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1700
1736
|
}
|
|
1701
1737
|
for (const [key, newValue, oldValue] of changes.replace) {
|
|
1702
1738
|
if (key === 'children') {
|
|
1739
|
+
updatedChildren = true;
|
|
1740
|
+
newAtom.child = createChildChain(newValue, isSvg);
|
|
1741
|
+
if (!newAtom.child) {
|
|
1742
|
+
cleanElementChildren(oldAtom, nativeRenderer);
|
|
1743
|
+
}
|
|
1744
|
+
else {
|
|
1745
|
+
diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, context, false);
|
|
1746
|
+
}
|
|
1703
1747
|
continue;
|
|
1704
1748
|
}
|
|
1705
1749
|
if (key === 'class') {
|
|
@@ -1734,6 +1778,9 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1734
1778
|
}
|
|
1735
1779
|
for (const [key, value] of changes.add) {
|
|
1736
1780
|
if (key === 'children') {
|
|
1781
|
+
updatedChildren = true;
|
|
1782
|
+
newAtom.child = createChildChain(value, isSvg);
|
|
1783
|
+
buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
|
|
1737
1784
|
continue;
|
|
1738
1785
|
}
|
|
1739
1786
|
if (key === 'class') {
|
|
@@ -1759,40 +1806,13 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1759
1806
|
}
|
|
1760
1807
|
nativeRenderer.setProperty(nativeNode, key, value, isSvg);
|
|
1761
1808
|
}
|
|
1762
|
-
|
|
1809
|
+
if (!updatedChildren) {
|
|
1810
|
+
newAtom.child = oldAtom.child;
|
|
1811
|
+
reuseElementChildrenView(nativeRenderer, newAtom);
|
|
1812
|
+
}
|
|
1763
1813
|
applyRefs(unBindRefs, nativeNode, false);
|
|
1764
1814
|
applyRefs(bindRefs, nativeNode, true);
|
|
1765
1815
|
}
|
|
1766
|
-
function updateElementChildren(newAtom, oldAtom, nativeRenderer, parentComponent, context, isSvg) {
|
|
1767
|
-
/**
|
|
1768
|
-
* 不能仅依赖 children 是否相等的判断来确定是否要继续向下 diff
|
|
1769
|
-
* 如:
|
|
1770
|
-
* ```tsx
|
|
1771
|
-
* <Comp>
|
|
1772
|
-
* <div>
|
|
1773
|
-
* {props.children}
|
|
1774
|
-
* </div>
|
|
1775
|
-
* </Comp>
|
|
1776
|
-
* ```
|
|
1777
|
-
* 其中当 Comp 产生变化时,children 来自父组件,这时 children 是相等的,
|
|
1778
|
-
* 但,children 内可能有子组件也发生了变化,如果不继续 diff,那么,子组件
|
|
1779
|
-
* 的视图更新将不会发生
|
|
1780
|
-
*/
|
|
1781
|
-
newAtom.child = createChildChain(newAtom.jsxNode.props.children, isSvg);
|
|
1782
|
-
if (!newAtom.child) {
|
|
1783
|
-
// 防止删除用户手动添加的元素
|
|
1784
|
-
if (oldAtom.child) {
|
|
1785
|
-
cleanElementChildren(oldAtom, nativeRenderer);
|
|
1786
|
-
}
|
|
1787
|
-
}
|
|
1788
|
-
else {
|
|
1789
|
-
diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, {
|
|
1790
|
-
host: newAtom.nativeNode,
|
|
1791
|
-
isParent: true,
|
|
1792
|
-
rootHost: context.rootHost
|
|
1793
|
-
}, false);
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
1816
|
function applyRefs(refs, nativeNode, binding) {
|
|
1797
1817
|
if (refs) {
|
|
1798
1818
|
const refList = Array.isArray(refs) ? refs : [refs];
|
|
@@ -1908,4 +1928,4 @@ function viewfly(config) {
|
|
|
1908
1928
|
return app;
|
|
1909
1929
|
}
|
|
1910
1930
|
|
|
1911
|
-
export { Component, DynamicRef, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, NativeRenderer, NullInjector, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, Type, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|
|
1931
|
+
export { Component, Context, DynamicRef, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, NativeRenderer, NullInjector, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, Type, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withAnnotation, withMemo };
|
package/bundles/index.js
CHANGED
|
@@ -694,7 +694,7 @@ class Component extends ReflectiveInjector {
|
|
|
694
694
|
this.parentComponent.markAsChanged(this);
|
|
695
695
|
}
|
|
696
696
|
}
|
|
697
|
-
render() {
|
|
697
|
+
render(update) {
|
|
698
698
|
const self = this;
|
|
699
699
|
const proxiesProps = new Proxy(this.props, {
|
|
700
700
|
get(_, key) {
|
|
@@ -736,19 +736,22 @@ class Component extends ReflectiveInjector {
|
|
|
736
736
|
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
737
737
|
this.markAsDirtied();
|
|
738
738
|
});
|
|
739
|
-
this.
|
|
740
|
-
|
|
741
|
-
template: template,
|
|
742
|
-
portalHost: this.instance.$portalHost
|
|
743
|
-
};
|
|
739
|
+
update(template, this.instance.$portalHost);
|
|
740
|
+
this.rendered();
|
|
744
741
|
}
|
|
745
|
-
update(newProps) {
|
|
742
|
+
update(newProps, updateChildren, reuseChildren) {
|
|
746
743
|
const oldProps = this.props;
|
|
747
744
|
if (newProps !== oldProps) {
|
|
748
745
|
const { add, remove, replace } = getObjectChanges(newProps, oldProps);
|
|
749
746
|
if (add.length || remove.length || replace.length) {
|
|
750
747
|
this.invokePropsChangedHooks(newProps);
|
|
751
748
|
}
|
|
749
|
+
else if (!this.dirty) {
|
|
750
|
+
this.props = newProps;
|
|
751
|
+
reuseChildren(false);
|
|
752
|
+
this.rendered();
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
752
755
|
const newRefs = toRefs(newProps.ref);
|
|
753
756
|
if (this.refs) {
|
|
754
757
|
for (const oldRef of this.refs) {
|
|
@@ -766,39 +769,25 @@ class Component extends ReflectiveInjector {
|
|
|
766
769
|
}
|
|
767
770
|
if (typeof this.instance.$useMemo === 'function') {
|
|
768
771
|
if (this.instance.$useMemo(newProps, oldProps)) {
|
|
769
|
-
|
|
772
|
+
reuseChildren(true);
|
|
773
|
+
this.rendered();
|
|
774
|
+
return;
|
|
770
775
|
}
|
|
771
776
|
}
|
|
772
777
|
this.unWatch();
|
|
773
778
|
signalDepsStack.push([]);
|
|
774
|
-
|
|
779
|
+
const template = this.instance.$render();
|
|
775
780
|
const deps = signalDepsStack.pop();
|
|
776
781
|
this.unWatch = watch(Array.from(new Set(deps)), () => {
|
|
777
782
|
this.markAsDirtied();
|
|
778
783
|
});
|
|
779
|
-
|
|
784
|
+
updateChildren(template);
|
|
785
|
+
this.rendered();
|
|
780
786
|
}
|
|
781
787
|
provide(providers) {
|
|
782
788
|
providers = Array.isArray(providers) ? providers : [providers];
|
|
783
789
|
this.normalizedProviders.unshift(...providers.map(i => normalizeProvider(i)));
|
|
784
790
|
}
|
|
785
|
-
rendered() {
|
|
786
|
-
this.changedSubComponents.clear();
|
|
787
|
-
const is = this.isFirstRendering;
|
|
788
|
-
this.isFirstRendering = false;
|
|
789
|
-
this._dirty = this._changed = false;
|
|
790
|
-
this.invokeUpdatedHooks();
|
|
791
|
-
if (is) {
|
|
792
|
-
this.invokeMountHooks();
|
|
793
|
-
}
|
|
794
|
-
if (this.changed) {
|
|
795
|
-
Promise.resolve().then(() => {
|
|
796
|
-
if (this.parentComponent instanceof Component) {
|
|
797
|
-
this.parentComponent.markAsChanged(this);
|
|
798
|
-
}
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
791
|
destroy() {
|
|
803
792
|
var _a, _b, _c;
|
|
804
793
|
this.unWatch();
|
|
@@ -818,6 +807,23 @@ class Component extends ReflectiveInjector {
|
|
|
818
807
|
this.propsChangedCallbacks =
|
|
819
808
|
this.unmountedCallbacks = null;
|
|
820
809
|
}
|
|
810
|
+
rendered() {
|
|
811
|
+
this.changedSubComponents.clear();
|
|
812
|
+
const is = this.isFirstRendering;
|
|
813
|
+
this.isFirstRendering = false;
|
|
814
|
+
this._dirty = this._changed = false;
|
|
815
|
+
this.invokeUpdatedHooks();
|
|
816
|
+
if (is) {
|
|
817
|
+
this.invokeMountHooks();
|
|
818
|
+
}
|
|
819
|
+
if (this.changed) {
|
|
820
|
+
Promise.resolve().then(() => {
|
|
821
|
+
if (this.parentComponent instanceof Component) {
|
|
822
|
+
this.parentComponent.markAsChanged(this);
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
}
|
|
821
827
|
invokePropsChangedHooks(newProps) {
|
|
822
828
|
const oldProps = this.props;
|
|
823
829
|
this.props = newProps;
|
|
@@ -1261,6 +1267,13 @@ function Fragment(props) {
|
|
|
1261
1267
|
return props.children;
|
|
1262
1268
|
};
|
|
1263
1269
|
}
|
|
1270
|
+
function Context(props) {
|
|
1271
|
+
const instance = getCurrentInstance();
|
|
1272
|
+
instance.provide(props.providers);
|
|
1273
|
+
return () => {
|
|
1274
|
+
return props.children;
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1264
1277
|
function jsx(type, props, key) {
|
|
1265
1278
|
return JSXNodeFactory.createNode(type, props, key);
|
|
1266
1279
|
}
|
|
@@ -1306,7 +1319,7 @@ function createRenderer(component, nativeRenderer) {
|
|
|
1306
1319
|
});
|
|
1307
1320
|
}
|
|
1308
1321
|
else {
|
|
1309
|
-
updateView(nativeRenderer, component);
|
|
1322
|
+
updateView(nativeRenderer, component, false);
|
|
1310
1323
|
}
|
|
1311
1324
|
};
|
|
1312
1325
|
}
|
|
@@ -1325,46 +1338,43 @@ function buildView(nativeRenderer, parentComponent, atom, context) {
|
|
|
1325
1338
|
}
|
|
1326
1339
|
}
|
|
1327
1340
|
function buildElementChildren(atom, nativeRenderer, parentComponent, context) {
|
|
1328
|
-
const childContext = {
|
|
1329
|
-
isParent: true,
|
|
1330
|
-
host: atom.nativeNode,
|
|
1331
|
-
rootHost: context.rootHost
|
|
1332
|
-
};
|
|
1333
1341
|
let child = atom.child;
|
|
1334
1342
|
while (child) {
|
|
1335
|
-
buildView(nativeRenderer, parentComponent, child,
|
|
1343
|
+
buildView(nativeRenderer, parentComponent, child, context);
|
|
1336
1344
|
child = child.sibling;
|
|
1337
1345
|
}
|
|
1338
1346
|
}
|
|
1339
|
-
function updateView(nativeRenderer, component) {
|
|
1347
|
+
function updateView(nativeRenderer, component, needMove) {
|
|
1340
1348
|
if (component.dirty) {
|
|
1341
|
-
|
|
1342
|
-
component
|
|
1349
|
+
const { atom, host, isParent, rootHost } = componentViewCache.get(component);
|
|
1350
|
+
applyChanges(nativeRenderer, component, atom, {
|
|
1351
|
+
host,
|
|
1352
|
+
isParent,
|
|
1353
|
+
rootHost
|
|
1354
|
+
}, needMove);
|
|
1343
1355
|
}
|
|
1344
1356
|
else if (component.changed) {
|
|
1345
1357
|
component.changedSubComponents.forEach(child => {
|
|
1346
|
-
updateView(nativeRenderer, child);
|
|
1358
|
+
updateView(nativeRenderer, child, needMove);
|
|
1347
1359
|
});
|
|
1348
1360
|
component.rendered();
|
|
1349
1361
|
}
|
|
1350
1362
|
}
|
|
1351
|
-
function applyChanges(nativeRenderer, component) {
|
|
1352
|
-
const { atom, host, isParent, rootHost } = componentViewCache.get(component);
|
|
1363
|
+
function applyChanges(nativeRenderer, component, atom, context, needMove) {
|
|
1353
1364
|
const diffAtom = atom.child;
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
}
|
|
1365
|
+
component.update(component.props, newTemplate => {
|
|
1366
|
+
atom.child = createChildChain(newTemplate, atom.isSvg);
|
|
1367
|
+
diff(nativeRenderer, component, atom.child, diffAtom, context, needMove);
|
|
1368
|
+
const next = atom.sibling;
|
|
1369
|
+
if (next && next.jsxNode instanceof Component) {
|
|
1370
|
+
const view = componentViewCache.get(next.jsxNode);
|
|
1371
|
+
view.host = context.host;
|
|
1372
|
+
view.isParent = context.isParent;
|
|
1373
|
+
}
|
|
1374
|
+
}, () => {
|
|
1375
|
+
// console.log(skipSubComponentDiff, '----')
|
|
1376
|
+
//
|
|
1377
|
+
});
|
|
1368
1378
|
}
|
|
1369
1379
|
function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
|
|
1370
1380
|
const commits = [];
|
|
@@ -1449,54 +1459,60 @@ function updateElement(newAtom, oldAtom, nativeRenderer, context, parentComponen
|
|
|
1449
1459
|
}
|
|
1450
1460
|
context.host = newAtom.nativeNode;
|
|
1451
1461
|
context.isParent = false;
|
|
1452
|
-
updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent,
|
|
1462
|
+
updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
|
|
1463
|
+
host: newAtom.nativeNode,
|
|
1464
|
+
isParent: true,
|
|
1465
|
+
rootHost: context.rootHost
|
|
1466
|
+
});
|
|
1453
1467
|
};
|
|
1454
1468
|
}
|
|
1455
1469
|
function updateComponent(newAtom, reusedAtom, nativeRenderer, context) {
|
|
1456
1470
|
return function (offset, needMove) {
|
|
1457
1471
|
const component = reusedAtom.jsxNode;
|
|
1458
1472
|
const newProps = newAtom.jsxNode.props;
|
|
1459
|
-
const oldTemplate = component.template;
|
|
1460
|
-
const newTemplate = component.update(newProps);
|
|
1461
1473
|
const portalHost = component.instance.$portalHost;
|
|
1462
1474
|
context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
|
|
1463
1475
|
componentViewCache.set(component, Object.assign({ atom: newAtom }, context));
|
|
1464
1476
|
newAtom.jsxNode = component;
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
component.rendered();
|
|
1469
|
-
return;
|
|
1470
|
-
}
|
|
1471
|
-
if (newTemplate) {
|
|
1472
|
-
newAtom.child = createChildChain(newTemplate, newAtom.isSvg);
|
|
1473
|
-
}
|
|
1474
|
-
if (newAtom.child) {
|
|
1475
|
-
diff(nativeRenderer, component, newAtom.child, reusedAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index);
|
|
1476
|
-
}
|
|
1477
|
-
else if (reusedAtom.child) {
|
|
1478
|
-
let atom = reusedAtom.child;
|
|
1479
|
-
while (atom) {
|
|
1480
|
-
cleanView(nativeRenderer, atom, true);
|
|
1481
|
-
atom = atom.sibling;
|
|
1477
|
+
component.update(newProps, newTemplate => {
|
|
1478
|
+
if (newTemplate) {
|
|
1479
|
+
newAtom.child = createChildChain(newTemplate, newAtom.isSvg);
|
|
1482
1480
|
}
|
|
1483
|
-
|
|
1484
|
-
|
|
1481
|
+
if (newAtom.child) {
|
|
1482
|
+
diff(nativeRenderer, component, newAtom.child, reusedAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index);
|
|
1483
|
+
}
|
|
1484
|
+
else if (reusedAtom.child) {
|
|
1485
|
+
let atom = reusedAtom.child;
|
|
1486
|
+
while (atom) {
|
|
1487
|
+
cleanView(nativeRenderer, atom, true);
|
|
1488
|
+
atom = atom.sibling;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
}, (skipSubComponentDiff) => {
|
|
1492
|
+
newAtom.child = reusedAtom.child;
|
|
1493
|
+
reuseComponentView(nativeRenderer, newAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index, skipSubComponentDiff);
|
|
1494
|
+
});
|
|
1485
1495
|
};
|
|
1486
1496
|
}
|
|
1487
|
-
function reuseComponentView(nativeRenderer, child, context, moveView) {
|
|
1497
|
+
function reuseComponentView(nativeRenderer, child, context, moveView, skipSubComponentDiff) {
|
|
1488
1498
|
const updateContext = (atom) => {
|
|
1489
1499
|
if (atom.jsxNode instanceof Component) {
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1500
|
+
if (skipSubComponentDiff || !moveView) {
|
|
1501
|
+
let child = atom.child;
|
|
1502
|
+
while (child) {
|
|
1503
|
+
updateContext(child);
|
|
1504
|
+
child = child.sibling;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
else {
|
|
1508
|
+
applyChanges(nativeRenderer, atom.jsxNode, atom, context, true);
|
|
1494
1509
|
}
|
|
1495
1510
|
}
|
|
1496
1511
|
else {
|
|
1497
1512
|
if (moveView) {
|
|
1498
1513
|
insertNode(nativeRenderer, atom, context);
|
|
1499
1514
|
}
|
|
1515
|
+
reuseElementChildrenView(nativeRenderer, atom);
|
|
1500
1516
|
context.isParent = false;
|
|
1501
1517
|
context.host = atom.nativeNode;
|
|
1502
1518
|
}
|
|
@@ -1506,6 +1522,18 @@ function reuseComponentView(nativeRenderer, child, context, moveView) {
|
|
|
1506
1522
|
child = child.sibling;
|
|
1507
1523
|
}
|
|
1508
1524
|
}
|
|
1525
|
+
function reuseElementChildrenView(nativeRenderer, atom, context, skipSubComponentDiff) {
|
|
1526
|
+
let child = atom.child;
|
|
1527
|
+
while (child) {
|
|
1528
|
+
if (child.jsxNode instanceof Component) {
|
|
1529
|
+
updateView(nativeRenderer, child.jsxNode, false);
|
|
1530
|
+
}
|
|
1531
|
+
else {
|
|
1532
|
+
reuseElementChildrenView(nativeRenderer, child);
|
|
1533
|
+
}
|
|
1534
|
+
child = child.sibling;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1509
1537
|
function cleanElementChildren(atom, nativeRenderer) {
|
|
1510
1538
|
let child = atom.child;
|
|
1511
1539
|
nativeRenderer.cleanChildren(atom.nativeNode, atom.isSvg);
|
|
@@ -1538,16 +1566,16 @@ function cleanView(nativeRenderer, atom, needClean) {
|
|
|
1538
1566
|
}
|
|
1539
1567
|
}
|
|
1540
1568
|
function componentRender(nativeRenderer, component, from, context) {
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1569
|
+
component.render((template, portalHost) => {
|
|
1570
|
+
from.child = createChildChain(template, from.isSvg);
|
|
1571
|
+
context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
|
|
1572
|
+
componentViewCache.set(component, Object.assign({ atom: from }, context));
|
|
1573
|
+
let child = from.child;
|
|
1574
|
+
while (child) {
|
|
1575
|
+
buildView(nativeRenderer, component, child, context);
|
|
1576
|
+
child = child.sibling;
|
|
1577
|
+
}
|
|
1578
|
+
});
|
|
1551
1579
|
}
|
|
1552
1580
|
function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, isSvg, key) {
|
|
1553
1581
|
const atom = {
|
|
@@ -1650,7 +1678,11 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
|
|
|
1650
1678
|
}
|
|
1651
1679
|
atom.nativeNode = nativeNode;
|
|
1652
1680
|
insertNode(nativeRenderer, atom, context);
|
|
1653
|
-
buildElementChildren(atom, nativeRenderer, parentComponent,
|
|
1681
|
+
buildElementChildren(atom, nativeRenderer, parentComponent, {
|
|
1682
|
+
isParent: true,
|
|
1683
|
+
host: nativeNode,
|
|
1684
|
+
rootHost: context.rootHost
|
|
1685
|
+
});
|
|
1654
1686
|
context.host = nativeNode;
|
|
1655
1687
|
context.isParent = false;
|
|
1656
1688
|
applyRefs(bindingRefs, nativeNode, true);
|
|
@@ -1668,14 +1700,18 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1668
1700
|
const nativeNode = newAtom.nativeNode;
|
|
1669
1701
|
const oldVNode = oldAtom.jsxNode;
|
|
1670
1702
|
if (newVNode === oldVNode) {
|
|
1671
|
-
|
|
1703
|
+
newAtom.child = oldAtom.child;
|
|
1704
|
+
reuseElementChildrenView(nativeRenderer, newAtom);
|
|
1672
1705
|
return;
|
|
1673
1706
|
}
|
|
1674
1707
|
const changes = getObjectChanges(newVNode.props, oldVNode.props);
|
|
1675
1708
|
let unBindRefs;
|
|
1676
1709
|
let bindRefs;
|
|
1710
|
+
let updatedChildren = false;
|
|
1677
1711
|
for (const [key, value] of changes.remove) {
|
|
1678
1712
|
if (key === 'children') {
|
|
1713
|
+
updatedChildren = true;
|
|
1714
|
+
cleanElementChildren(oldAtom, nativeRenderer);
|
|
1679
1715
|
continue;
|
|
1680
1716
|
}
|
|
1681
1717
|
if (key === 'class') {
|
|
@@ -1702,6 +1738,14 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1702
1738
|
}
|
|
1703
1739
|
for (const [key, newValue, oldValue] of changes.replace) {
|
|
1704
1740
|
if (key === 'children') {
|
|
1741
|
+
updatedChildren = true;
|
|
1742
|
+
newAtom.child = createChildChain(newValue, isSvg);
|
|
1743
|
+
if (!newAtom.child) {
|
|
1744
|
+
cleanElementChildren(oldAtom, nativeRenderer);
|
|
1745
|
+
}
|
|
1746
|
+
else {
|
|
1747
|
+
diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, context, false);
|
|
1748
|
+
}
|
|
1705
1749
|
continue;
|
|
1706
1750
|
}
|
|
1707
1751
|
if (key === 'class') {
|
|
@@ -1736,6 +1780,9 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1736
1780
|
}
|
|
1737
1781
|
for (const [key, value] of changes.add) {
|
|
1738
1782
|
if (key === 'children') {
|
|
1783
|
+
updatedChildren = true;
|
|
1784
|
+
newAtom.child = createChildChain(value, isSvg);
|
|
1785
|
+
buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
|
|
1739
1786
|
continue;
|
|
1740
1787
|
}
|
|
1741
1788
|
if (key === 'class') {
|
|
@@ -1761,40 +1808,13 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
|
|
|
1761
1808
|
}
|
|
1762
1809
|
nativeRenderer.setProperty(nativeNode, key, value, isSvg);
|
|
1763
1810
|
}
|
|
1764
|
-
|
|
1811
|
+
if (!updatedChildren) {
|
|
1812
|
+
newAtom.child = oldAtom.child;
|
|
1813
|
+
reuseElementChildrenView(nativeRenderer, newAtom);
|
|
1814
|
+
}
|
|
1765
1815
|
applyRefs(unBindRefs, nativeNode, false);
|
|
1766
1816
|
applyRefs(bindRefs, nativeNode, true);
|
|
1767
1817
|
}
|
|
1768
|
-
function updateElementChildren(newAtom, oldAtom, nativeRenderer, parentComponent, context, isSvg) {
|
|
1769
|
-
/**
|
|
1770
|
-
* 不能仅依赖 children 是否相等的判断来确定是否要继续向下 diff
|
|
1771
|
-
* 如:
|
|
1772
|
-
* ```tsx
|
|
1773
|
-
* <Comp>
|
|
1774
|
-
* <div>
|
|
1775
|
-
* {props.children}
|
|
1776
|
-
* </div>
|
|
1777
|
-
* </Comp>
|
|
1778
|
-
* ```
|
|
1779
|
-
* 其中当 Comp 产生变化时,children 来自父组件,这时 children 是相等的,
|
|
1780
|
-
* 但,children 内可能有子组件也发生了变化,如果不继续 diff,那么,子组件
|
|
1781
|
-
* 的视图更新将不会发生
|
|
1782
|
-
*/
|
|
1783
|
-
newAtom.child = createChildChain(newAtom.jsxNode.props.children, isSvg);
|
|
1784
|
-
if (!newAtom.child) {
|
|
1785
|
-
// 防止删除用户手动添加的元素
|
|
1786
|
-
if (oldAtom.child) {
|
|
1787
|
-
cleanElementChildren(oldAtom, nativeRenderer);
|
|
1788
|
-
}
|
|
1789
|
-
}
|
|
1790
|
-
else {
|
|
1791
|
-
diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, {
|
|
1792
|
-
host: newAtom.nativeNode,
|
|
1793
|
-
isParent: true,
|
|
1794
|
-
rootHost: context.rootHost
|
|
1795
|
-
}, false);
|
|
1796
|
-
}
|
|
1797
|
-
}
|
|
1798
1818
|
function applyRefs(refs, nativeNode, binding) {
|
|
1799
1819
|
if (refs) {
|
|
1800
1820
|
const refList = Array.isArray(refs) ? refs : [refs];
|
|
@@ -1911,6 +1931,7 @@ function viewfly(config) {
|
|
|
1911
1931
|
}
|
|
1912
1932
|
|
|
1913
1933
|
exports.Component = Component;
|
|
1934
|
+
exports.Context = Context;
|
|
1914
1935
|
exports.DynamicRef = DynamicRef;
|
|
1915
1936
|
exports.ForwardRef = ForwardRef;
|
|
1916
1937
|
exports.Fragment = Fragment;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viewfly/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Viewfly is a simple and easy-to-use JavaScript framework with an intuitive development experience.",
|
|
5
5
|
"main": "./bundles/index.js",
|
|
6
6
|
"module": "./bundles/index.esm.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"bugs": {
|
|
51
51
|
"url": "https://github.com/viewfly/viewfly.git/issues"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "b66ca589f7662cd518fc2e5955b3e3ff9de83f94",
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"reflect-metadata": "^0.2.2"
|
|
56
56
|
}
|