@viewfly/core 1.0.0-alpha.12 → 1.0.0-alpha.14

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.
@@ -113,7 +113,7 @@ interface Prop {
113
113
  declare const Prop: PropDecorator;
114
114
 
115
115
  declare const THROW_IF_NOT_FOUND: any;
116
- declare class NullInjector extends Injector {
116
+ declare class NullInjector implements Injector {
117
117
  parentInjector: null;
118
118
  get(token: any, notFoundValue?: any, _?: InjectFlags): any;
119
119
  }
@@ -167,9 +167,8 @@ declare function normalizeProvider(provider: Provider): NormalizedProvider;
167
167
  /**
168
168
  * 反射注入器
169
169
  */
170
- declare class ReflectiveInjector extends Injector {
170
+ declare class ReflectiveInjector implements Injector {
171
171
  parentInjector: Injector | null;
172
- protected staticProviders: Provider[];
173
172
  protected scope?: Scope | undefined;
174
173
  protected normalizedProviders: NormalizedProvider[];
175
174
  protected recordValues: Map<Type<any> | AbstractType<any> | InjectionToken<any>, any>;
@@ -211,45 +210,6 @@ declare abstract class NativeRenderer<ElementNode = NativeNode, TextNode = Nativ
211
210
  abstract insertAfter(newNode: ElementNode | TextNode, ref: ElementNode | TextNode, isSvg: boolean): void;
212
211
  }
213
212
 
214
- interface ListenDelegate {
215
- delegate: () => any;
216
- listenFn: ((...args: any[]) => any) | void;
217
- }
218
- interface TextAtom {
219
- type: 'text';
220
- index: number;
221
- jsxNode: string;
222
- nativeNode: NativeNode | null;
223
- child: Atom | null;
224
- sibling: Atom | null;
225
- isSvg: boolean;
226
- }
227
- interface ElementAtom {
228
- type: 'element';
229
- index: number;
230
- jsxNode: JSXNode<string>;
231
- nativeNode: NativeNode | null;
232
- child: Atom | null;
233
- sibling: Atom | null;
234
- isSvg: boolean;
235
- }
236
- interface ComponentAtom {
237
- type: 'component';
238
- index: number;
239
- jsxNode: JSXNode<JSXInternal.ComponentSetup> | Component;
240
- nativeNode: NativeNode | null;
241
- child: Atom | null;
242
- sibling: Atom | null;
243
- isSvg: boolean;
244
- }
245
- type Atom = TextAtom | ElementAtom | ComponentAtom;
246
- interface ComponentView {
247
- atom: Atom;
248
- host: NativeNode;
249
- isParent: boolean;
250
- rootHost: NativeNode;
251
- }
252
-
253
213
  interface Props {
254
214
  children?: JSXInternal.ViewNode | JSXInternal.ViewNode[];
255
215
  }
@@ -261,7 +221,6 @@ interface JSXNode<T = string | JSXInternal.ComponentSetup> {
261
221
  type: T;
262
222
  props: Props & Record<string, any>;
263
223
  key?: Key;
264
- on?: Record<string, ListenDelegate>;
265
224
  }
266
225
  declare const JSXNodeFactory: {
267
226
  createNode<T = string | JSXInternal.ComponentSetup<any>>(type: T, props: Props & Record<string, any>, key?: Key): JSXNode<T>;
@@ -560,6 +519,50 @@ declare global {
560
519
  }
561
520
  }
562
521
 
522
+ declare const TextAtomType: unique symbol;
523
+ declare const ElementAtomType: unique symbol;
524
+ declare const ComponentAtomType: unique symbol;
525
+ interface TextAtom {
526
+ type: typeof TextAtomType;
527
+ index: number;
528
+ jsxNode: string;
529
+ nativeNode: NativeNode | null;
530
+ child: Atom | null;
531
+ sibling: Atom | null;
532
+ isSvg: boolean;
533
+ update: null | ((insertOffset: number) => void);
534
+ next: Atom | null;
535
+ }
536
+ interface ElementAtom {
537
+ type: typeof ElementAtomType;
538
+ index: number;
539
+ jsxNode: JSXNode<string>;
540
+ nativeNode: NativeNode | null;
541
+ child: Atom | null;
542
+ sibling: Atom | null;
543
+ isSvg: boolean;
544
+ update: null | ((insertOffset: number) => void);
545
+ next: Atom | null;
546
+ }
547
+ interface ComponentAtom {
548
+ type: typeof ComponentAtomType;
549
+ index: number;
550
+ jsxNode: JSXNode<JSXInternal.ComponentSetup> | Component;
551
+ nativeNode: NativeNode | null;
552
+ child: Atom | null;
553
+ sibling: Atom | null;
554
+ isSvg: boolean;
555
+ update: null | ((insertOffset: number) => void);
556
+ next: Atom | null;
557
+ }
558
+ type Atom = TextAtom | ElementAtom | ComponentAtom;
559
+ interface ComponentView {
560
+ atom: Atom;
561
+ host: NativeNode;
562
+ isParent: boolean;
563
+ rootHost: NativeNode;
564
+ }
565
+
563
566
  /**
564
567
  * Viewfly 配置项
565
568
  */
@@ -234,9 +234,8 @@ const THROW_IF_NOT_FOUND = {
234
234
  const nullInjectorErrorFn = (token) => {
235
235
  return makeError('NullInjector')(`No provide for \`${stringify(token)}\`!`);
236
236
  };
237
- class NullInjector extends Injector {
237
+ class NullInjector {
238
238
  constructor() {
239
- super(...arguments);
240
239
  this.parentInjector = null;
241
240
  }
242
241
  /* eslint-disable-next-line */
@@ -411,11 +410,9 @@ const provideScopeError = (token) => {
411
410
  /**
412
411
  * 反射注入器
413
412
  */
414
- class ReflectiveInjector extends Injector {
413
+ class ReflectiveInjector {
415
414
  constructor(parentInjector, staticProviders, scope) {
416
- super();
417
415
  this.parentInjector = parentInjector;
418
- this.staticProviders = staticProviders;
419
416
  this.scope = scope;
420
417
  this.recordValues = new Map();
421
418
  this.normalizedProviders = staticProviders.map(provide => {
@@ -634,6 +631,9 @@ function styleToObject(style) {
634
631
  });
635
632
  return obj;
636
633
  }
634
+ const TextAtomType = Symbol('Text');
635
+ const ElementAtomType = Symbol('Element');
636
+ const ComponentAtomType = Symbol('Component');
637
637
 
638
638
  const componentSetupStack = [];
639
639
  const signalDepsStack = [];
@@ -741,8 +741,9 @@ class Component extends ReflectiveInjector {
741
741
  };
742
742
  }
743
743
  update(newProps, forceUpdate = false) {
744
+ const oldProps = this.props;
744
745
  if (!forceUpdate) {
745
- const { add, remove, replace } = getObjectChanges(newProps, this.props);
746
+ const { add, remove, replace } = getObjectChanges(newProps, oldProps);
746
747
  if (add.length || remove.length || replace.length) {
747
748
  this.invokePropsChangedHooks(newProps);
748
749
  }
@@ -766,7 +767,7 @@ class Component extends ReflectiveInjector {
766
767
  }
767
768
  }
768
769
  if (typeof this.instance.$useMemo === 'function') {
769
- if (this.instance.$useMemo(newProps, this.props)) {
770
+ if (this.instance.$useMemo(newProps, oldProps)) {
770
771
  return this.template;
771
772
  }
772
773
  }
@@ -1291,13 +1292,15 @@ function createRenderer(component, nativeRenderer) {
1291
1292
  if (isInit) {
1292
1293
  isInit = false;
1293
1294
  const atom = {
1294
- type: 'component',
1295
+ type: ComponentAtomType,
1295
1296
  index: 0,
1296
1297
  jsxNode: component,
1297
1298
  sibling: null,
1298
1299
  child: null,
1299
1300
  nativeNode: null,
1300
- isSvg: false
1301
+ isSvg: false,
1302
+ update: null,
1303
+ next: null
1301
1304
  };
1302
1305
  componentRender(nativeRenderer, component, atom, {
1303
1306
  isParent: true,
@@ -1312,12 +1315,12 @@ function createRenderer(component, nativeRenderer) {
1312
1315
  }
1313
1316
  function buildView(nativeRenderer, parentComponent, atom, context) {
1314
1317
  const { jsxNode, type } = atom;
1315
- if (type === 'component') {
1318
+ if (type === ComponentAtomType) {
1316
1319
  const component = new Component(parentComponent, jsxNode.type, jsxNode.props, jsxNode.key);
1317
1320
  atom.jsxNode = component;
1318
1321
  componentRender(nativeRenderer, component, atom, context);
1319
1322
  }
1320
- else if (type === 'element') {
1323
+ else if (type === ElementAtomType) {
1321
1324
  createElement(nativeRenderer, atom, parentComponent, context);
1322
1325
  }
1323
1326
  else {
@@ -1367,72 +1370,61 @@ function applyChanges(nativeRenderer, component) {
1367
1370
  }
1368
1371
  }
1369
1372
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context) {
1370
- const commits = [];
1371
- function changeOffset() {
1372
- offset++;
1373
- }
1374
- while (newAtom) {
1375
- oldAtom = createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, changeOffset);
1376
- newAtom = newAtom.sibling;
1377
- }
1378
- let dirtyDiffAtom = oldAtom;
1379
- while (dirtyDiffAtom) {
1380
- cleanView(nativeRenderer, dirtyDiffAtom, true);
1381
- dirtyDiffAtom = dirtyDiffAtom.sibling;
1382
- }
1383
- let offset = 0;
1384
- for (let i = 0; i < commits.length; i++) {
1385
- const commit = commits[i];
1386
- while (oldAtom) {
1387
- if (oldAtom.index <= i) {
1388
- offset--;
1389
- oldAtom = oldAtom.sibling;
1390
- continue;
1391
- }
1392
- break;
1393
- }
1394
- commit(offset);
1395
- }
1396
- }
1397
- function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, effect) {
1398
- const startDiffAtom = oldAtom;
1399
- const { jsxNode: newJsxNode, type } = newAtom;
1400
- const key = newJsxNode.key;
1401
- let prev = null;
1373
+ let updateAtom = newAtom;
1374
+ let insertOffset = 0;
1375
+ let deleteOffset = 0;
1402
1376
  while (oldAtom) {
1403
- const diffIndex = oldAtom.index;
1404
- if (type === oldAtom.type) {
1405
- let commit;
1406
- if (type === 'text') {
1407
- commit = updateText(newAtom, oldAtom, nativeRenderer, context);
1408
- }
1409
- else {
1410
- const { key: diffKey, type: diffType } = oldAtom.jsxNode;
1411
- if (diffKey !== key || newJsxNode.type !== diffType) {
1412
- prev = oldAtom;
1413
- oldAtom = oldAtom.sibling;
1414
- continue;
1415
- }
1416
- if (type === 'component') {
1417
- commit = updateComponent(newAtom, oldAtom, newAtom.index, diffIndex, nativeRenderer, context);
1377
+ const startDiffAtom = newAtom;
1378
+ let prev = null;
1379
+ let isUsed = false;
1380
+ while (newAtom) {
1381
+ const newAtomType = newAtom.type;
1382
+ if (oldAtom.type === newAtomType) {
1383
+ if (newAtomType === TextAtomType) {
1384
+ newAtom.update = updateText(newAtom, oldAtom, nativeRenderer, context);
1385
+ isUsed = true;
1418
1386
  }
1419
1387
  else {
1420
- commit = updateElement(newAtom, oldAtom, newAtom.index, diffIndex, nativeRenderer, context, parentComponent);
1388
+ const { key: newKey, type: newType } = newAtom.jsxNode;
1389
+ const { key: oldKey, type: oldType } = oldAtom.jsxNode;
1390
+ if (newType === oldType && newKey === oldKey) {
1391
+ if (newAtomType === ComponentAtomType) {
1392
+ newAtom.update = updateComponent(newAtom, oldAtom, deleteOffset, nativeRenderer, context);
1393
+ }
1394
+ else {
1395
+ newAtom.update = updateElement(newAtom, oldAtom, deleteOffset, nativeRenderer, context, parentComponent);
1396
+ }
1397
+ isUsed = true;
1398
+ }
1421
1399
  }
1422
1400
  }
1423
- commits.push(commit);
1424
- const next = oldAtom.sibling;
1425
- if (!prev) {
1426
- return next;
1401
+ if (isUsed) {
1402
+ const sibling = newAtom.next || newAtom.sibling;
1403
+ if (prev) {
1404
+ prev.next = sibling;
1405
+ }
1406
+ newAtom = newAtom === startDiffAtom ? sibling : startDiffAtom;
1407
+ break;
1427
1408
  }
1428
- prev.sibling = next;
1429
- return startDiffAtom;
1409
+ prev = newAtom;
1410
+ newAtom = newAtom.next || newAtom.sibling;
1411
+ }
1412
+ if (!isUsed) {
1413
+ newAtom = startDiffAtom;
1414
+ deleteOffset++;
1415
+ cleanView(nativeRenderer, oldAtom, true);
1430
1416
  }
1431
- prev = oldAtom;
1432
1417
  oldAtom = oldAtom.sibling;
1433
1418
  }
1434
- commits.push(createNewView(newAtom, nativeRenderer, context, parentComponent, effect));
1435
- return startDiffAtom;
1419
+ function changeOffset() {
1420
+ insertOffset++;
1421
+ }
1422
+ while (updateAtom) {
1423
+ const update = updateAtom.update || createNewView(updateAtom, nativeRenderer, context, parentComponent, changeOffset);
1424
+ update(insertOffset);
1425
+ updateAtom.next = updateAtom.update = null;
1426
+ updateAtom = updateAtom.sibling;
1427
+ }
1436
1428
  }
1437
1429
  function createNewView(start, nativeRenderer, context, parentComponent, effect) {
1438
1430
  return function () {
@@ -1451,10 +1443,10 @@ function updateText(newAtom, oldAtom, nativeRenderer, context) {
1451
1443
  context.isParent = false;
1452
1444
  };
1453
1445
  }
1454
- function updateElement(newAtom, oldAtom, expectIndex, oldIndex, nativeRenderer, context, parentComponent) {
1455
- return function (offset) {
1446
+ function updateElement(newAtom, oldAtom, deleteOffset, nativeRenderer, context, parentComponent) {
1447
+ return function (insertOffset) {
1456
1448
  newAtom.nativeNode = oldAtom.nativeNode;
1457
- if (expectIndex - offset !== oldIndex) {
1449
+ if (newAtom.index - insertOffset !== oldAtom.index - deleteOffset) {
1458
1450
  insertNode(nativeRenderer, newAtom, context);
1459
1451
  }
1460
1452
  context.host = newAtom.nativeNode;
@@ -1462,8 +1454,8 @@ function updateElement(newAtom, oldAtom, expectIndex, oldIndex, nativeRenderer,
1462
1454
  updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, context);
1463
1455
  };
1464
1456
  }
1465
- function updateComponent(newAtom, reusedAtom, expectIndex, oldIndex, nativeRenderer, context) {
1466
- return function (offset) {
1457
+ function updateComponent(newAtom, reusedAtom, deleteOffset, nativeRenderer, context) {
1458
+ return function (insertOffset) {
1467
1459
  const component = reusedAtom.jsxNode;
1468
1460
  const newProps = newAtom.jsxNode.props;
1469
1461
  const oldTemplate = component.template;
@@ -1473,7 +1465,7 @@ function updateComponent(newAtom, reusedAtom, expectIndex, oldIndex, nativeRende
1473
1465
  componentViewCache.set(component, Object.assign({ atom: newAtom }, context));
1474
1466
  newAtom.jsxNode = component;
1475
1467
  if (newTemplate === oldTemplate) {
1476
- reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, expectIndex - offset !== oldIndex);
1468
+ reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, newAtom.index - insertOffset !== reusedAtom.index - deleteOffset);
1477
1469
  updateView(nativeRenderer, component);
1478
1470
  return;
1479
1471
  }
@@ -1531,7 +1523,7 @@ function cleanView(nativeRenderer, atom, needClean) {
1531
1523
  nativeRenderer.remove(atom.nativeNode, atom.isSvg);
1532
1524
  needClean = false;
1533
1525
  }
1534
- if (atom.type === 'element') {
1526
+ if (atom.type === ElementAtomType) {
1535
1527
  const ref = atom.jsxNode.props[refKey];
1536
1528
  applyRefs(ref, atom.nativeNode, false);
1537
1529
  }
@@ -1560,42 +1552,17 @@ function componentRender(nativeRenderer, component, from, context) {
1560
1552
  }
1561
1553
  component.rendered();
1562
1554
  }
1563
- function createChainByJSXComponent(jsxNode, prevAtom, isSvg) {
1564
- const atom = {
1565
- type: 'component',
1566
- index: prevAtom.index + 1,
1567
- jsxNode,
1568
- sibling: null,
1569
- child: null,
1570
- nativeNode: null,
1571
- isSvg
1572
- };
1573
- prevAtom.sibling = atom;
1574
- return atom;
1575
- }
1576
- function createChainByJSXText(jsxNode, prevAtom, isSvg) {
1555
+ function createChainByJSXNode(type, jsxNode, prevAtom, isSvg) {
1577
1556
  const atom = {
1578
- type: 'text',
1557
+ type,
1579
1558
  index: prevAtom.index + 1,
1580
1559
  jsxNode,
1581
1560
  sibling: null,
1582
1561
  child: null,
1583
1562
  nativeNode: null,
1584
- isSvg
1585
- };
1586
- prevAtom.sibling = atom;
1587
- return atom;
1588
- }
1589
- function createChainByJSXElement(element, prevAtom, isSvg) {
1590
- isSvg = isSvg || element.type === 'svg';
1591
- const atom = {
1592
- type: 'element',
1593
- index: prevAtom.index + 1,
1594
- jsxNode: element,
1595
- sibling: null,
1596
- child: null,
1597
- nativeNode: null,
1598
- isSvg
1563
+ isSvg,
1564
+ update: null,
1565
+ next: null
1599
1566
  };
1600
1567
  prevAtom.sibling = atom;
1601
1568
  return atom;
@@ -1604,7 +1571,7 @@ function createChainByNode(jsxNode, prevAtom, isSvg) {
1604
1571
  const type = typeof jsxNode;
1605
1572
  if (jsxNode !== null && type !== 'undefined' && type !== 'boolean') {
1606
1573
  if (typeof jsxNode === 'string') {
1607
- return createChainByJSXText(jsxNode, prevAtom, isSvg);
1574
+ return createChainByJSXNode(TextAtomType, jsxNode, prevAtom, isSvg);
1608
1575
  }
1609
1576
  if (Array.isArray(jsxNode)) {
1610
1577
  return createChainByChildren(jsxNode, prevAtom, isSvg);
@@ -1612,13 +1579,13 @@ function createChainByNode(jsxNode, prevAtom, isSvg) {
1612
1579
  if (type === 'object') {
1613
1580
  const nodeType = typeof jsxNode.type;
1614
1581
  if (nodeType === 'string') {
1615
- return createChainByJSXElement(jsxNode, prevAtom, isSvg);
1582
+ return createChainByJSXNode(ElementAtomType, jsxNode, prevAtom, isSvg || jsxNode.type === 'svg');
1616
1583
  }
1617
1584
  else if (nodeType === 'function') {
1618
- return createChainByJSXComponent(jsxNode, prevAtom, isSvg);
1585
+ return createChainByJSXNode(ComponentAtomType, jsxNode, prevAtom, isSvg);
1619
1586
  }
1620
1587
  }
1621
- return createChainByJSXText(String(jsxNode), prevAtom, isSvg);
1588
+ return createChainByJSXNode(TextAtomType, String(jsxNode), prevAtom, isSvg);
1622
1589
  }
1623
1590
  return prevAtom;
1624
1591
  }
@@ -1673,7 +1640,7 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
1673
1640
  if (listenerReg.test(key)) {
1674
1641
  const listener = props[key];
1675
1642
  if (typeof listener === 'function') {
1676
- bindEvent(nativeRenderer, jsxNode, key, nativeNode, listener, isSvg);
1643
+ nativeRenderer.listen(nativeNode, key, listener, isSvg);
1677
1644
  }
1678
1645
  continue;
1679
1646
  }
@@ -1711,7 +1678,6 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1711
1678
  const changes = getObjectChanges(newVNode.props, oldVNode.props);
1712
1679
  let unBindRefs;
1713
1680
  let bindRefs;
1714
- newVNode.on = oldVNode.on;
1715
1681
  newAtom.child = oldAtom.child;
1716
1682
  for (const [key, value] of changes.remove) {
1717
1683
  if (key === 'children') {
@@ -1731,9 +1697,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1731
1697
  }
1732
1698
  if (listenerReg.test(key)) {
1733
1699
  if (typeof value === 'function') {
1734
- const oldOn = oldVNode.on;
1735
- nativeRenderer.unListen(nativeNode, key, oldOn[key].delegate, isSvg);
1736
- Reflect.deleteProperty(oldOn, key);
1700
+ nativeRenderer.unListen(nativeNode, key, value, isSvg);
1737
1701
  }
1738
1702
  continue;
1739
1703
  }
@@ -1777,7 +1741,8 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1777
1741
  continue;
1778
1742
  }
1779
1743
  if (listenerReg.test(key)) {
1780
- newVNode.on[key].listenFn = newValue;
1744
+ nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
1745
+ nativeRenderer.listen(nativeNode, key, newValue, isSvg);
1781
1746
  continue;
1782
1747
  }
1783
1748
  if (key === refKey) {
@@ -1806,7 +1771,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1806
1771
  }
1807
1772
  if (listenerReg.test(key)) {
1808
1773
  if (typeof value === 'function') {
1809
- bindEvent(nativeRenderer, newVNode, key, nativeNode, value, isSvg);
1774
+ nativeRenderer.listen(nativeNode, key, value, isSvg);
1810
1775
  }
1811
1776
  continue;
1812
1777
  }
@@ -1829,20 +1794,6 @@ function applyRefs(refs, nativeNode, binding) {
1829
1794
  }
1830
1795
  }
1831
1796
  }
1832
- function bindEvent(nativeRenderer, vNode, key, nativeNode, listenFn, isSvg) {
1833
- let on = vNode.on;
1834
- if (!on) {
1835
- vNode.on = on = {};
1836
- }
1837
- const delegateObj = {
1838
- delegate(...args) {
1839
- return delegateObj.listenFn.apply(this, args);
1840
- },
1841
- listenFn
1842
- };
1843
- on[key] = delegateObj;
1844
- nativeRenderer.listen(nativeNode, key, delegateObj.delegate, isSvg);
1845
- }
1846
1797
 
1847
1798
  /**
1848
1799
  * Viewfly 根组件,用于实现组件状态更新事件通知
package/bundles/index.js CHANGED
@@ -236,9 +236,8 @@ const THROW_IF_NOT_FOUND = {
236
236
  const nullInjectorErrorFn = (token) => {
237
237
  return makeError('NullInjector')(`No provide for \`${stringify(token)}\`!`);
238
238
  };
239
- class NullInjector extends Injector {
239
+ class NullInjector {
240
240
  constructor() {
241
- super(...arguments);
242
241
  this.parentInjector = null;
243
242
  }
244
243
  /* eslint-disable-next-line */
@@ -413,11 +412,9 @@ const provideScopeError = (token) => {
413
412
  /**
414
413
  * 反射注入器
415
414
  */
416
- class ReflectiveInjector extends Injector {
415
+ class ReflectiveInjector {
417
416
  constructor(parentInjector, staticProviders, scope) {
418
- super();
419
417
  this.parentInjector = parentInjector;
420
- this.staticProviders = staticProviders;
421
418
  this.scope = scope;
422
419
  this.recordValues = new Map();
423
420
  this.normalizedProviders = staticProviders.map(provide => {
@@ -636,6 +633,9 @@ function styleToObject(style) {
636
633
  });
637
634
  return obj;
638
635
  }
636
+ const TextAtomType = Symbol('Text');
637
+ const ElementAtomType = Symbol('Element');
638
+ const ComponentAtomType = Symbol('Component');
639
639
 
640
640
  const componentSetupStack = [];
641
641
  const signalDepsStack = [];
@@ -743,8 +743,9 @@ class Component extends ReflectiveInjector {
743
743
  };
744
744
  }
745
745
  update(newProps, forceUpdate = false) {
746
+ const oldProps = this.props;
746
747
  if (!forceUpdate) {
747
- const { add, remove, replace } = getObjectChanges(newProps, this.props);
748
+ const { add, remove, replace } = getObjectChanges(newProps, oldProps);
748
749
  if (add.length || remove.length || replace.length) {
749
750
  this.invokePropsChangedHooks(newProps);
750
751
  }
@@ -768,7 +769,7 @@ class Component extends ReflectiveInjector {
768
769
  }
769
770
  }
770
771
  if (typeof this.instance.$useMemo === 'function') {
771
- if (this.instance.$useMemo(newProps, this.props)) {
772
+ if (this.instance.$useMemo(newProps, oldProps)) {
772
773
  return this.template;
773
774
  }
774
775
  }
@@ -1293,13 +1294,15 @@ function createRenderer(component, nativeRenderer) {
1293
1294
  if (isInit) {
1294
1295
  isInit = false;
1295
1296
  const atom = {
1296
- type: 'component',
1297
+ type: ComponentAtomType,
1297
1298
  index: 0,
1298
1299
  jsxNode: component,
1299
1300
  sibling: null,
1300
1301
  child: null,
1301
1302
  nativeNode: null,
1302
- isSvg: false
1303
+ isSvg: false,
1304
+ update: null,
1305
+ next: null
1303
1306
  };
1304
1307
  componentRender(nativeRenderer, component, atom, {
1305
1308
  isParent: true,
@@ -1314,12 +1317,12 @@ function createRenderer(component, nativeRenderer) {
1314
1317
  }
1315
1318
  function buildView(nativeRenderer, parentComponent, atom, context) {
1316
1319
  const { jsxNode, type } = atom;
1317
- if (type === 'component') {
1320
+ if (type === ComponentAtomType) {
1318
1321
  const component = new Component(parentComponent, jsxNode.type, jsxNode.props, jsxNode.key);
1319
1322
  atom.jsxNode = component;
1320
1323
  componentRender(nativeRenderer, component, atom, context);
1321
1324
  }
1322
- else if (type === 'element') {
1325
+ else if (type === ElementAtomType) {
1323
1326
  createElement(nativeRenderer, atom, parentComponent, context);
1324
1327
  }
1325
1328
  else {
@@ -1369,72 +1372,61 @@ function applyChanges(nativeRenderer, component) {
1369
1372
  }
1370
1373
  }
1371
1374
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context) {
1372
- const commits = [];
1373
- function changeOffset() {
1374
- offset++;
1375
- }
1376
- while (newAtom) {
1377
- oldAtom = createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, changeOffset);
1378
- newAtom = newAtom.sibling;
1379
- }
1380
- let dirtyDiffAtom = oldAtom;
1381
- while (dirtyDiffAtom) {
1382
- cleanView(nativeRenderer, dirtyDiffAtom, true);
1383
- dirtyDiffAtom = dirtyDiffAtom.sibling;
1384
- }
1385
- let offset = 0;
1386
- for (let i = 0; i < commits.length; i++) {
1387
- const commit = commits[i];
1388
- while (oldAtom) {
1389
- if (oldAtom.index <= i) {
1390
- offset--;
1391
- oldAtom = oldAtom.sibling;
1392
- continue;
1393
- }
1394
- break;
1395
- }
1396
- commit(offset);
1397
- }
1398
- }
1399
- function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, effect) {
1400
- const startDiffAtom = oldAtom;
1401
- const { jsxNode: newJsxNode, type } = newAtom;
1402
- const key = newJsxNode.key;
1403
- let prev = null;
1375
+ let updateAtom = newAtom;
1376
+ let insertOffset = 0;
1377
+ let deleteOffset = 0;
1404
1378
  while (oldAtom) {
1405
- const diffIndex = oldAtom.index;
1406
- if (type === oldAtom.type) {
1407
- let commit;
1408
- if (type === 'text') {
1409
- commit = updateText(newAtom, oldAtom, nativeRenderer, context);
1410
- }
1411
- else {
1412
- const { key: diffKey, type: diffType } = oldAtom.jsxNode;
1413
- if (diffKey !== key || newJsxNode.type !== diffType) {
1414
- prev = oldAtom;
1415
- oldAtom = oldAtom.sibling;
1416
- continue;
1417
- }
1418
- if (type === 'component') {
1419
- commit = updateComponent(newAtom, oldAtom, newAtom.index, diffIndex, nativeRenderer, context);
1379
+ const startDiffAtom = newAtom;
1380
+ let prev = null;
1381
+ let isUsed = false;
1382
+ while (newAtom) {
1383
+ const newAtomType = newAtom.type;
1384
+ if (oldAtom.type === newAtomType) {
1385
+ if (newAtomType === TextAtomType) {
1386
+ newAtom.update = updateText(newAtom, oldAtom, nativeRenderer, context);
1387
+ isUsed = true;
1420
1388
  }
1421
1389
  else {
1422
- commit = updateElement(newAtom, oldAtom, newAtom.index, diffIndex, nativeRenderer, context, parentComponent);
1390
+ const { key: newKey, type: newType } = newAtom.jsxNode;
1391
+ const { key: oldKey, type: oldType } = oldAtom.jsxNode;
1392
+ if (newType === oldType && newKey === oldKey) {
1393
+ if (newAtomType === ComponentAtomType) {
1394
+ newAtom.update = updateComponent(newAtom, oldAtom, deleteOffset, nativeRenderer, context);
1395
+ }
1396
+ else {
1397
+ newAtom.update = updateElement(newAtom, oldAtom, deleteOffset, nativeRenderer, context, parentComponent);
1398
+ }
1399
+ isUsed = true;
1400
+ }
1423
1401
  }
1424
1402
  }
1425
- commits.push(commit);
1426
- const next = oldAtom.sibling;
1427
- if (!prev) {
1428
- return next;
1403
+ if (isUsed) {
1404
+ const sibling = newAtom.next || newAtom.sibling;
1405
+ if (prev) {
1406
+ prev.next = sibling;
1407
+ }
1408
+ newAtom = newAtom === startDiffAtom ? sibling : startDiffAtom;
1409
+ break;
1429
1410
  }
1430
- prev.sibling = next;
1431
- return startDiffAtom;
1411
+ prev = newAtom;
1412
+ newAtom = newAtom.next || newAtom.sibling;
1413
+ }
1414
+ if (!isUsed) {
1415
+ newAtom = startDiffAtom;
1416
+ deleteOffset++;
1417
+ cleanView(nativeRenderer, oldAtom, true);
1432
1418
  }
1433
- prev = oldAtom;
1434
1419
  oldAtom = oldAtom.sibling;
1435
1420
  }
1436
- commits.push(createNewView(newAtom, nativeRenderer, context, parentComponent, effect));
1437
- return startDiffAtom;
1421
+ function changeOffset() {
1422
+ insertOffset++;
1423
+ }
1424
+ while (updateAtom) {
1425
+ const update = updateAtom.update || createNewView(updateAtom, nativeRenderer, context, parentComponent, changeOffset);
1426
+ update(insertOffset);
1427
+ updateAtom.next = updateAtom.update = null;
1428
+ updateAtom = updateAtom.sibling;
1429
+ }
1438
1430
  }
1439
1431
  function createNewView(start, nativeRenderer, context, parentComponent, effect) {
1440
1432
  return function () {
@@ -1453,10 +1445,10 @@ function updateText(newAtom, oldAtom, nativeRenderer, context) {
1453
1445
  context.isParent = false;
1454
1446
  };
1455
1447
  }
1456
- function updateElement(newAtom, oldAtom, expectIndex, oldIndex, nativeRenderer, context, parentComponent) {
1457
- return function (offset) {
1448
+ function updateElement(newAtom, oldAtom, deleteOffset, nativeRenderer, context, parentComponent) {
1449
+ return function (insertOffset) {
1458
1450
  newAtom.nativeNode = oldAtom.nativeNode;
1459
- if (expectIndex - offset !== oldIndex) {
1451
+ if (newAtom.index - insertOffset !== oldAtom.index - deleteOffset) {
1460
1452
  insertNode(nativeRenderer, newAtom, context);
1461
1453
  }
1462
1454
  context.host = newAtom.nativeNode;
@@ -1464,8 +1456,8 @@ function updateElement(newAtom, oldAtom, expectIndex, oldIndex, nativeRenderer,
1464
1456
  updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, context);
1465
1457
  };
1466
1458
  }
1467
- function updateComponent(newAtom, reusedAtom, expectIndex, oldIndex, nativeRenderer, context) {
1468
- return function (offset) {
1459
+ function updateComponent(newAtom, reusedAtom, deleteOffset, nativeRenderer, context) {
1460
+ return function (insertOffset) {
1469
1461
  const component = reusedAtom.jsxNode;
1470
1462
  const newProps = newAtom.jsxNode.props;
1471
1463
  const oldTemplate = component.template;
@@ -1475,7 +1467,7 @@ function updateComponent(newAtom, reusedAtom, expectIndex, oldIndex, nativeRende
1475
1467
  componentViewCache.set(component, Object.assign({ atom: newAtom }, context));
1476
1468
  newAtom.jsxNode = component;
1477
1469
  if (newTemplate === oldTemplate) {
1478
- reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, expectIndex - offset !== oldIndex);
1470
+ reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, newAtom.index - insertOffset !== reusedAtom.index - deleteOffset);
1479
1471
  updateView(nativeRenderer, component);
1480
1472
  return;
1481
1473
  }
@@ -1533,7 +1525,7 @@ function cleanView(nativeRenderer, atom, needClean) {
1533
1525
  nativeRenderer.remove(atom.nativeNode, atom.isSvg);
1534
1526
  needClean = false;
1535
1527
  }
1536
- if (atom.type === 'element') {
1528
+ if (atom.type === ElementAtomType) {
1537
1529
  const ref = atom.jsxNode.props[refKey];
1538
1530
  applyRefs(ref, atom.nativeNode, false);
1539
1531
  }
@@ -1562,42 +1554,17 @@ function componentRender(nativeRenderer, component, from, context) {
1562
1554
  }
1563
1555
  component.rendered();
1564
1556
  }
1565
- function createChainByJSXComponent(jsxNode, prevAtom, isSvg) {
1566
- const atom = {
1567
- type: 'component',
1568
- index: prevAtom.index + 1,
1569
- jsxNode,
1570
- sibling: null,
1571
- child: null,
1572
- nativeNode: null,
1573
- isSvg
1574
- };
1575
- prevAtom.sibling = atom;
1576
- return atom;
1577
- }
1578
- function createChainByJSXText(jsxNode, prevAtom, isSvg) {
1557
+ function createChainByJSXNode(type, jsxNode, prevAtom, isSvg) {
1579
1558
  const atom = {
1580
- type: 'text',
1559
+ type,
1581
1560
  index: prevAtom.index + 1,
1582
1561
  jsxNode,
1583
1562
  sibling: null,
1584
1563
  child: null,
1585
1564
  nativeNode: null,
1586
- isSvg
1587
- };
1588
- prevAtom.sibling = atom;
1589
- return atom;
1590
- }
1591
- function createChainByJSXElement(element, prevAtom, isSvg) {
1592
- isSvg = isSvg || element.type === 'svg';
1593
- const atom = {
1594
- type: 'element',
1595
- index: prevAtom.index + 1,
1596
- jsxNode: element,
1597
- sibling: null,
1598
- child: null,
1599
- nativeNode: null,
1600
- isSvg
1565
+ isSvg,
1566
+ update: null,
1567
+ next: null
1601
1568
  };
1602
1569
  prevAtom.sibling = atom;
1603
1570
  return atom;
@@ -1606,7 +1573,7 @@ function createChainByNode(jsxNode, prevAtom, isSvg) {
1606
1573
  const type = typeof jsxNode;
1607
1574
  if (jsxNode !== null && type !== 'undefined' && type !== 'boolean') {
1608
1575
  if (typeof jsxNode === 'string') {
1609
- return createChainByJSXText(jsxNode, prevAtom, isSvg);
1576
+ return createChainByJSXNode(TextAtomType, jsxNode, prevAtom, isSvg);
1610
1577
  }
1611
1578
  if (Array.isArray(jsxNode)) {
1612
1579
  return createChainByChildren(jsxNode, prevAtom, isSvg);
@@ -1614,13 +1581,13 @@ function createChainByNode(jsxNode, prevAtom, isSvg) {
1614
1581
  if (type === 'object') {
1615
1582
  const nodeType = typeof jsxNode.type;
1616
1583
  if (nodeType === 'string') {
1617
- return createChainByJSXElement(jsxNode, prevAtom, isSvg);
1584
+ return createChainByJSXNode(ElementAtomType, jsxNode, prevAtom, isSvg || jsxNode.type === 'svg');
1618
1585
  }
1619
1586
  else if (nodeType === 'function') {
1620
- return createChainByJSXComponent(jsxNode, prevAtom, isSvg);
1587
+ return createChainByJSXNode(ComponentAtomType, jsxNode, prevAtom, isSvg);
1621
1588
  }
1622
1589
  }
1623
- return createChainByJSXText(String(jsxNode), prevAtom, isSvg);
1590
+ return createChainByJSXNode(TextAtomType, String(jsxNode), prevAtom, isSvg);
1624
1591
  }
1625
1592
  return prevAtom;
1626
1593
  }
@@ -1675,7 +1642,7 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
1675
1642
  if (listenerReg.test(key)) {
1676
1643
  const listener = props[key];
1677
1644
  if (typeof listener === 'function') {
1678
- bindEvent(nativeRenderer, jsxNode, key, nativeNode, listener, isSvg);
1645
+ nativeRenderer.listen(nativeNode, key, listener, isSvg);
1679
1646
  }
1680
1647
  continue;
1681
1648
  }
@@ -1713,7 +1680,6 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1713
1680
  const changes = getObjectChanges(newVNode.props, oldVNode.props);
1714
1681
  let unBindRefs;
1715
1682
  let bindRefs;
1716
- newVNode.on = oldVNode.on;
1717
1683
  newAtom.child = oldAtom.child;
1718
1684
  for (const [key, value] of changes.remove) {
1719
1685
  if (key === 'children') {
@@ -1733,9 +1699,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1733
1699
  }
1734
1700
  if (listenerReg.test(key)) {
1735
1701
  if (typeof value === 'function') {
1736
- const oldOn = oldVNode.on;
1737
- nativeRenderer.unListen(nativeNode, key, oldOn[key].delegate, isSvg);
1738
- Reflect.deleteProperty(oldOn, key);
1702
+ nativeRenderer.unListen(nativeNode, key, value, isSvg);
1739
1703
  }
1740
1704
  continue;
1741
1705
  }
@@ -1779,7 +1743,8 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1779
1743
  continue;
1780
1744
  }
1781
1745
  if (listenerReg.test(key)) {
1782
- newVNode.on[key].listenFn = newValue;
1746
+ nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
1747
+ nativeRenderer.listen(nativeNode, key, newValue, isSvg);
1783
1748
  continue;
1784
1749
  }
1785
1750
  if (key === refKey) {
@@ -1808,7 +1773,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1808
1773
  }
1809
1774
  if (listenerReg.test(key)) {
1810
1775
  if (typeof value === 'function') {
1811
- bindEvent(nativeRenderer, newVNode, key, nativeNode, value, isSvg);
1776
+ nativeRenderer.listen(nativeNode, key, value, isSvg);
1812
1777
  }
1813
1778
  continue;
1814
1779
  }
@@ -1831,20 +1796,6 @@ function applyRefs(refs, nativeNode, binding) {
1831
1796
  }
1832
1797
  }
1833
1798
  }
1834
- function bindEvent(nativeRenderer, vNode, key, nativeNode, listenFn, isSvg) {
1835
- let on = vNode.on;
1836
- if (!on) {
1837
- vNode.on = on = {};
1838
- }
1839
- const delegateObj = {
1840
- delegate(...args) {
1841
- return delegateObj.listenFn.apply(this, args);
1842
- },
1843
- listenFn
1844
- };
1845
- on[key] = delegateObj;
1846
- nativeRenderer.listen(nativeNode, key, delegateObj.delegate, isSvg);
1847
- }
1848
1799
 
1849
1800
  /**
1850
1801
  * Viewfly 根组件,用于实现组件状态更新事件通知
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viewfly/core",
3
- "version": "1.0.0-alpha.12",
3
+ "version": "1.0.0-alpha.14",
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": "9e55375068bc3657f348f4b0be498111b61eee3c",
53
+ "gitHead": "48779d88f1390751bbd06e4c4581bf3dbe613a26",
54
54
  "dependencies": {
55
55
  "reflect-metadata": "^0.2.2"
56
56
  }