@viewfly/core 1.0.0-alpha.2 → 1.0.0-alpha.20

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.
@@ -161,6 +161,40 @@ var InjectFlags;
161
161
  class Injector {
162
162
  }
163
163
 
164
+ /**
165
+ * 构造函数参数装饰器,用于改变注入 token
166
+ */
167
+ const Inject = function InjectDecorator(token) {
168
+ if (this instanceof Inject) {
169
+ this.token = token;
170
+ }
171
+ else {
172
+ return makeParamDecorator(Inject, new Inject(token));
173
+ }
174
+ };
175
+ const Self = function SelfDecorator() {
176
+ if (!(this instanceof Self)) {
177
+ return makeParamDecorator(Self, new Self());
178
+ }
179
+ };
180
+ const SkipSelf = function SkipSelfDecorator() {
181
+ if (!(this instanceof SkipSelf)) {
182
+ return makeParamDecorator(SkipSelf, new SkipSelf());
183
+ }
184
+ };
185
+ const Optional = function OptionalDecorator() {
186
+ if (!(this instanceof Optional)) {
187
+ return makeParamDecorator(Optional, new Optional());
188
+ }
189
+ };
190
+ const Prop = function PropDecorator(token, notFoundValue, flags) {
191
+ if (!(this instanceof Prop)) {
192
+ return makePropertyDecorator(Prop, token, function (instance, propertyName, token, injector) {
193
+ instance[propertyName] = injector.get(token instanceof ForwardRef ? token.getRef() : token, notFoundValue, flags);
194
+ });
195
+ }
196
+ };
197
+
164
198
  function stringify(token) {
165
199
  if (typeof token === 'string') {
166
200
  return token;
@@ -200,12 +234,12 @@ const THROW_IF_NOT_FOUND = {
200
234
  const nullInjectorErrorFn = (token) => {
201
235
  return makeError('NullInjector')(`No provide for \`${stringify(token)}\`!`);
202
236
  };
203
- class NullInjector extends Injector {
237
+ class NullInjector {
204
238
  constructor() {
205
- super(...arguments);
206
239
  this.parentInjector = null;
207
240
  }
208
- get(token, flag, notFoundValue = THROW_IF_NOT_FOUND) {
241
+ /* eslint-disable-next-line */
242
+ get(token, notFoundValue = THROW_IF_NOT_FOUND, _) {
209
243
  if (notFoundValue === THROW_IF_NOT_FOUND) {
210
244
  throw nullInjectorErrorFn(token);
211
245
  }
@@ -213,40 +247,6 @@ class NullInjector extends Injector {
213
247
  }
214
248
  }
215
249
 
216
- /**
217
- * 构造函数参数装饰器,用于改变注入 token
218
- */
219
- const Inject = function InjectDecorator(token) {
220
- if (this instanceof Inject) {
221
- this.token = token;
222
- }
223
- else {
224
- return makeParamDecorator(Inject, new Inject(token));
225
- }
226
- };
227
- const Self = function SelfDecorator() {
228
- if (!(this instanceof Self)) {
229
- return makeParamDecorator(Self, new Self());
230
- }
231
- };
232
- const SkipSelf = function SkipSelfDecorator() {
233
- if (!(this instanceof SkipSelf)) {
234
- return makeParamDecorator(SkipSelf, new SkipSelf());
235
- }
236
- };
237
- const Optional = function OptionalDecorator() {
238
- if (!(this instanceof Optional)) {
239
- return makeParamDecorator(Optional, new Optional());
240
- }
241
- };
242
- const Prop = function PropDecorator(token, flags, notFoundValue = THROW_IF_NOT_FOUND) {
243
- if (!(this instanceof Prop)) {
244
- return makePropertyDecorator(Prop, token, function (instance, propertyName, token, injector) {
245
- instance[propertyName] = injector.get(token instanceof ForwardRef ? token.getRef() : token, flags, notFoundValue);
246
- });
247
- }
248
- };
249
-
250
250
  /**
251
251
  * 标准化 provide,并返回统一数据结构
252
252
  * @param provider
@@ -410,11 +410,9 @@ const provideScopeError = (token) => {
410
410
  /**
411
411
  * 反射注入器
412
412
  */
413
- class ReflectiveInjector extends Injector {
413
+ class ReflectiveInjector {
414
414
  constructor(parentInjector, staticProviders, scope) {
415
- super();
416
415
  this.parentInjector = parentInjector;
417
- this.staticProviders = staticProviders;
418
416
  this.scope = scope;
419
417
  this.recordValues = new Map();
420
418
  this.normalizedProviders = staticProviders.map(provide => {
@@ -424,15 +422,15 @@ class ReflectiveInjector extends Injector {
424
422
  /**
425
423
  * 用于获取当前注入器上下文内的实例、对象或数据
426
424
  * @param token 访问 token
427
- * @param flags 查询规则
428
425
  * @param notFoundValue 如未查找到的返回值
426
+ * @param flags 查询规则
429
427
  */
430
- get(token, flags = InjectFlags.Default, notFoundValue = THROW_IF_NOT_FOUND) {
428
+ get(token, notFoundValue = THROW_IF_NOT_FOUND, flags) {
431
429
  var _a;
432
430
  flags = flags || InjectFlags.Default;
433
431
  if (flags === InjectFlags.SkipSelf) {
434
432
  if (this.parentInjector) {
435
- return this.parentInjector.get(token, InjectFlags.Default, notFoundValue);
433
+ return this.parentInjector.get(token, notFoundValue);
436
434
  }
437
435
  if (notFoundValue !== THROW_IF_NOT_FOUND) {
438
436
  return notFoundValue;
@@ -476,9 +474,12 @@ class ReflectiveInjector extends Injector {
476
474
  return notFoundValue;
477
475
  }
478
476
  if (this.parentInjector) {
479
- return this.parentInjector.get(token, flags === InjectFlags.Optional ? InjectFlags.Optional : InjectFlags.Default, notFoundValue);
477
+ return this.parentInjector.get(token, notFoundValue, flags === InjectFlags.Optional ? InjectFlags.Optional : InjectFlags.Default);
480
478
  }
481
479
  if (notFoundValue === THROW_IF_NOT_FOUND) {
480
+ // if (flags === InjectFlags.Optional) {
481
+ // return null as U
482
+ // }
482
483
  throw reflectiveInjectorErrorFn(token);
483
484
  }
484
485
  return notFoundValue;
@@ -508,11 +509,11 @@ class ReflectiveInjector extends Injector {
508
509
  const tryValue = {};
509
510
  const injectToken = dep.injectKey instanceof ForwardRef ? dep.injectKey.getRef() : dep.injectKey;
510
511
  if (dep.visibility instanceof Self) {
511
- reflectiveValue = this.get(injectToken, InjectFlags.Self, tryValue);
512
+ reflectiveValue = this.get(injectToken, tryValue, InjectFlags.Self);
512
513
  }
513
514
  else if (dep.visibility instanceof SkipSelf) {
514
515
  if (this.parentInjector) {
515
- reflectiveValue = this.parentInjector.get(injectToken, InjectFlags.Default, tryValue);
516
+ reflectiveValue = this.parentInjector.get(injectToken, tryValue);
516
517
  }
517
518
  else {
518
519
  if (dep.optional) {
@@ -525,7 +526,7 @@ class ReflectiveInjector extends Injector {
525
526
  }
526
527
  }
527
528
  else {
528
- reflectiveValue = this.get(injectToken, InjectFlags.Default, tryValue);
529
+ reflectiveValue = this.get(injectToken, tryValue);
529
530
  }
530
531
  if (reflectiveValue === tryValue) {
531
532
  if (dep.optional) {
@@ -587,13 +588,13 @@ function getArrayChanges(left, right) {
587
588
  return changes;
588
589
  }
589
590
  function classToString(config) {
590
- if (!config) {
591
- return '';
592
- }
593
591
  if (typeof config === 'string') {
594
592
  return config;
595
593
  }
596
- else if (Array.isArray(config)) {
594
+ if (!config) {
595
+ return '';
596
+ }
597
+ if (Array.isArray(config)) {
597
598
  const classes = [];
598
599
  for (const i of config) {
599
600
  const v = classToString(i);
@@ -603,7 +604,7 @@ function classToString(config) {
603
604
  }
604
605
  return classes.join(' ');
605
606
  }
606
- else if (typeof config === 'object') {
607
+ if (typeof config === 'object') {
607
608
  if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
608
609
  return config.toString();
609
610
  }
@@ -630,6 +631,9 @@ function styleToObject(style) {
630
631
  });
631
632
  return obj;
632
633
  }
634
+ const TextAtomType = Symbol('Text');
635
+ const ElementAtomType = Symbol('Element');
636
+ const ComponentAtomType = Symbol('Component');
633
637
 
634
638
  const componentSetupStack = [];
635
639
  const signalDepsStack = [];
@@ -738,28 +742,31 @@ class Component extends ReflectiveInjector {
738
742
  }
739
743
  update(newProps, forceUpdate = false) {
740
744
  const oldProps = this.props;
741
- const { add, remove, replace } = getObjectChanges(newProps, this.props);
742
- if (add.length || remove.length || replace.length) {
743
- this.invokePropsChangedHooks(newProps);
744
- }
745
- else if (!this.dirty) {
746
- return this.template;
747
- }
748
- const newRefs = toRefs(newProps.ref);
749
- if (this.refs) {
750
- for (const oldRef of this.refs) {
751
- if (!newRefs.includes(oldRef)) {
752
- oldRef.unBind(this.instance);
745
+ if (!forceUpdate) {
746
+ const { add, remove, replace } = getObjectChanges(newProps, oldProps);
747
+ if (add.length || remove.length || replace.length) {
748
+ this.invokePropsChangedHooks(newProps);
749
+ }
750
+ else if (!this.dirty) {
751
+ this.props = newProps;
752
+ return this.template;
753
+ }
754
+ const newRefs = toRefs(newProps.ref);
755
+ if (this.refs) {
756
+ for (const oldRef of this.refs) {
757
+ if (!newRefs.includes(oldRef)) {
758
+ oldRef.unBind(this.instance);
759
+ }
753
760
  }
754
761
  }
762
+ for (const newRef of newRefs) {
763
+ newRef.bind(this.instance);
764
+ }
765
+ if (newRefs.length) {
766
+ this.refs = newRefs;
767
+ }
755
768
  }
756
- for (const newRef of newRefs) {
757
- newRef.bind(this.instance);
758
- }
759
- if (newRefs.length) {
760
- this.refs = newRefs;
761
- }
762
- if (!forceUpdate && typeof this.instance.$useMemo === 'function') {
769
+ if (typeof this.instance.$useMemo === 'function') {
763
770
  if (this.instance.$useMemo(newProps, oldProps)) {
764
771
  return this.template;
765
772
  }
@@ -843,7 +850,12 @@ class Component extends ReflectiveInjector {
843
850
  }
844
851
  }
845
852
  if (unmountedCallbacks.length) {
846
- this.unmountedCallbacks = unmountedCallbacks;
853
+ if (this.unmountedCallbacks) {
854
+ this.unmountedCallbacks.push(...unmountedCallbacks);
855
+ }
856
+ else {
857
+ this.unmountedCallbacks = unmountedCallbacks;
858
+ }
847
859
  }
848
860
  this.mountCallbacks = null;
849
861
  }
@@ -1232,9 +1244,9 @@ function withAnnotation(annotation, componentSetup) {
1232
1244
  /**
1233
1245
  * 通过组件上下文获取 IoC 容器内数据的勾子方法
1234
1246
  */
1235
- function inject(token, flags = InjectFlags.Default, notFoundValue = THROW_IF_NOT_FOUND) {
1247
+ function inject(token, notFoundValue = THROW_IF_NOT_FOUND, flags) {
1236
1248
  const component = getSetupContext();
1237
- return component.get(token, flags, notFoundValue);
1249
+ return component.get(token, notFoundValue, flags);
1238
1250
  }
1239
1251
  /**
1240
1252
  * 获取当前组件实例
@@ -1272,14 +1284,17 @@ function withMemo(canUseMemo, render) {
1272
1284
  };
1273
1285
  }
1274
1286
 
1275
- const listenerReg = /^on(?=[A-Z])/;
1287
+ const componentViewCache = new WeakMap();
1288
+ const listenerReg = /^on[A-Z]/;
1276
1289
  function createRenderer(component, nativeRenderer) {
1277
1290
  let isInit = true;
1278
1291
  return function render(host) {
1279
1292
  if (isInit) {
1280
1293
  isInit = false;
1281
1294
  const atom = {
1282
- type: 'component',
1295
+ type: ComponentAtomType,
1296
+ index: 0,
1297
+ nodeType: component.type,
1283
1298
  jsxNode: component,
1284
1299
  sibling: null,
1285
1300
  child: null,
@@ -1299,41 +1314,28 @@ function createRenderer(component, nativeRenderer) {
1299
1314
  }
1300
1315
  function buildView(nativeRenderer, parentComponent, atom, context) {
1301
1316
  const { jsxNode, type } = atom;
1302
- if (type === 'component') {
1317
+ if (type === ComponentAtomType) {
1303
1318
  const component = new Component(parentComponent, jsxNode.type, jsxNode.props, jsxNode.key);
1304
1319
  atom.jsxNode = component;
1305
1320
  componentRender(nativeRenderer, component, atom, context);
1306
1321
  }
1322
+ else if (type === ElementAtomType) {
1323
+ createElement(nativeRenderer, atom, parentComponent, context);
1324
+ }
1307
1325
  else {
1308
- let nativeNode;
1309
- let applyRefs = null;
1310
- if (type === 'element') {
1311
- const { nativeNode: n, applyRefs: a } = createElement(nativeRenderer, jsxNode, atom.isSvg);
1312
- nativeNode = n;
1313
- applyRefs = a;
1314
- }
1315
- else {
1316
- nativeNode = createTextNode(nativeRenderer, jsxNode, atom.isSvg);
1317
- }
1318
- atom.nativeNode = nativeNode;
1319
- insertNode(nativeRenderer, atom, context);
1320
- if (type === 'element') {
1321
- const childContext = {
1322
- isParent: true,
1323
- host: nativeNode,
1324
- rootHost: context.rootHost
1325
- };
1326
- let child = atom.child;
1327
- while (child) {
1328
- buildView(nativeRenderer, parentComponent, child, childContext);
1329
- child = child.sibling;
1330
- }
1331
- }
1332
- context.host = nativeNode;
1333
- context.isParent = false;
1334
- if (applyRefs) {
1335
- applyRefs();
1336
- }
1326
+ createTextNode(nativeRenderer, atom, context);
1327
+ }
1328
+ }
1329
+ function buildElementChildren(atom, nativeRenderer, parentComponent, context) {
1330
+ const childContext = {
1331
+ isParent: true,
1332
+ host: atom.nativeNode,
1333
+ rootHost: context.rootHost
1334
+ };
1335
+ let child = atom.child;
1336
+ while (child) {
1337
+ buildView(nativeRenderer, parentComponent, child, childContext);
1338
+ child = child.sibling;
1337
1339
  }
1338
1340
  }
1339
1341
  function updateView(nativeRenderer, component) {
@@ -1349,7 +1351,7 @@ function updateView(nativeRenderer, component) {
1349
1351
  }
1350
1352
  }
1351
1353
  function applyChanges(nativeRenderer, component) {
1352
- const { atom, host, isParent, rootHost } = component.$$view;
1354
+ const { atom, host, isParent, rootHost } = componentViewCache.get(component);
1353
1355
  const diffAtom = atom.child;
1354
1356
  const template = component.update(component.props, true);
1355
1357
  atom.child = createChildChain(template, atom.isSvg);
@@ -1358,58 +1360,35 @@ function applyChanges(nativeRenderer, component) {
1358
1360
  isParent,
1359
1361
  rootHost
1360
1362
  };
1361
- diff(nativeRenderer, component, atom.child, diffAtom, context, 0, 0);
1363
+ diff(nativeRenderer, component, atom.child, diffAtom, context);
1362
1364
  const next = atom.sibling;
1363
1365
  if (next && next.jsxNode instanceof Component) {
1364
- next.jsxNode.$$view.host = context.host;
1365
- next.jsxNode.$$view.isParent = context.isParent;
1366
- }
1367
- }
1368
- function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, expectIndex, index) {
1369
- let prevDiffAtom = null;
1370
- let firstDiffAtomIndexed = null;
1371
- if (oldAtom) {
1372
- prevDiffAtom = {
1373
- index,
1374
- atom: oldAtom,
1375
- prev: null
1376
- };
1377
- index++;
1378
- firstDiffAtomIndexed = prevDiffAtom;
1379
- oldAtom = oldAtom.sibling;
1380
- while (oldAtom) {
1381
- const diffAtom = {
1382
- index,
1383
- atom: oldAtom,
1384
- prev: prevDiffAtom
1385
- };
1386
- prevDiffAtom.next = diffAtom;
1387
- prevDiffAtom = diffAtom;
1388
- oldAtom = oldAtom.sibling;
1389
- index++;
1390
- }
1366
+ const view = componentViewCache.get(next.jsxNode);
1367
+ view.host = context.host;
1368
+ view.isParent = context.isParent;
1391
1369
  }
1370
+ }
1371
+ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context) {
1392
1372
  const commits = [];
1393
1373
  function changeOffset() {
1394
1374
  offset++;
1395
1375
  }
1396
1376
  while (newAtom) {
1397
- firstDiffAtomIndexed = createChanges(newAtom, expectIndex, firstDiffAtomIndexed, nativeRenderer, commits, context, parentComponent, changeOffset);
1377
+ oldAtom = createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, changeOffset);
1398
1378
  newAtom = newAtom.sibling;
1399
- expectIndex++;
1400
1379
  }
1401
- let dirtyDiffAtom = firstDiffAtomIndexed;
1380
+ let dirtyDiffAtom = oldAtom;
1402
1381
  while (dirtyDiffAtom) {
1403
- cleanView(nativeRenderer, dirtyDiffAtom.atom, false);
1404
- dirtyDiffAtom = dirtyDiffAtom.next;
1382
+ cleanView(nativeRenderer, dirtyDiffAtom, true);
1383
+ dirtyDiffAtom = dirtyDiffAtom.sibling;
1405
1384
  }
1406
1385
  let offset = 0;
1407
1386
  for (let i = 0; i < commits.length; i++) {
1408
1387
  const commit = commits[i];
1409
- while (firstDiffAtomIndexed) {
1410
- if (firstDiffAtomIndexed.index <= i) {
1388
+ while (oldAtom) {
1389
+ if (oldAtom.index <= i) {
1411
1390
  offset--;
1412
- firstDiffAtomIndexed = firstDiffAtomIndexed.next;
1391
+ oldAtom = oldAtom.sibling;
1413
1392
  continue;
1414
1393
  }
1415
1394
  break;
@@ -1417,47 +1396,32 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, expect
1417
1396
  commit(offset);
1418
1397
  }
1419
1398
  }
1420
- function createChanges(newAtom, expectIndex, diffAtomIndexed, nativeRenderer, commits, context, parentComponent, effect) {
1421
- const startDiffAtom = diffAtomIndexed;
1422
- const { jsxNode: newJsxNode, type } = newAtom;
1423
- const key = newJsxNode.key;
1424
- while (diffAtomIndexed) {
1425
- const { atom: diffAtom, index: diffIndex } = diffAtomIndexed;
1426
- if (type === diffAtom.type) {
1399
+ function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, effect) {
1400
+ const startDiffAtom = oldAtom;
1401
+ let prev = null;
1402
+ while (oldAtom) {
1403
+ const newAtomType = newAtom.type;
1404
+ if (oldAtom.type === newAtomType && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1427
1405
  let commit;
1428
- if (type === 'text') {
1429
- commit = updateText(newAtom, diffAtom, nativeRenderer, context);
1406
+ if (newAtomType === TextAtomType) {
1407
+ commit = updateText(newAtom, oldAtom, nativeRenderer, context);
1408
+ }
1409
+ else if (newAtomType === ComponentAtomType) {
1410
+ commit = updateComponent(newAtom, oldAtom, nativeRenderer, context);
1430
1411
  }
1431
1412
  else {
1432
- const { key: diffKey, type: diffType } = diffAtom.jsxNode;
1433
- if (diffKey !== key || newJsxNode.type !== diffType) {
1434
- diffAtomIndexed = diffAtomIndexed.next;
1435
- continue;
1436
- }
1437
- if (type === 'component') {
1438
- commit = updateComponent(newAtom, diffAtom, expectIndex, diffIndex, nativeRenderer, context);
1439
- }
1440
- else {
1441
- commit = updateElement(newAtom, diffAtom, expectIndex, diffIndex, nativeRenderer, context, parentComponent);
1442
- }
1413
+ commit = updateElement(newAtom, oldAtom, nativeRenderer, context, parentComponent);
1443
1414
  }
1444
1415
  commits.push(commit);
1445
- const next = diffAtomIndexed.next;
1446
- const prev = diffAtomIndexed.prev;
1416
+ const next = oldAtom.sibling;
1447
1417
  if (!prev) {
1448
- diffAtomIndexed = next;
1449
- if (diffAtomIndexed) {
1450
- diffAtomIndexed.prev = null;
1451
- }
1452
- return diffAtomIndexed;
1453
- }
1454
- prev.next = next;
1455
- if (next) {
1456
- next.prev = prev;
1418
+ return next;
1457
1419
  }
1420
+ prev.sibling = next;
1458
1421
  return startDiffAtom;
1459
1422
  }
1460
- diffAtomIndexed = diffAtomIndexed.next;
1423
+ prev = oldAtom;
1424
+ oldAtom = oldAtom.sibling;
1461
1425
  }
1462
1426
  commits.push(createNewView(newAtom, nativeRenderer, context, parentComponent, effect));
1463
1427
  return startDiffAtom;
@@ -1469,44 +1433,28 @@ function createNewView(start, nativeRenderer, context, parentComponent, effect)
1469
1433
  };
1470
1434
  }
1471
1435
  function updateText(newAtom, oldAtom, nativeRenderer, context) {
1472
- return function () {
1436
+ return function (offset) {
1473
1437
  const nativeNode = oldAtom.nativeNode;
1474
- if (newAtom.jsxNode !== oldAtom.jsxNode) {
1475
- nativeRenderer.syncTextContent(nativeNode, newAtom.jsxNode, newAtom.isSvg);
1476
- }
1477
1438
  newAtom.nativeNode = nativeNode;
1439
+ if (newAtom.index - offset !== oldAtom.index) {
1440
+ insertNode(nativeRenderer, newAtom, context);
1441
+ }
1478
1442
  context.host = nativeNode;
1479
1443
  context.isParent = false;
1480
1444
  };
1481
1445
  }
1482
- function updateElement(newAtom, oldAtom, expectIndex, oldIndex, nativeRenderer, context, parentComponent) {
1446
+ function updateElement(newAtom, oldAtom, nativeRenderer, context, parentComponent) {
1483
1447
  return function (offset) {
1484
1448
  newAtom.nativeNode = oldAtom.nativeNode;
1485
- if (expectIndex - offset !== oldIndex) {
1449
+ if (newAtom.index - offset !== oldAtom.index) {
1486
1450
  insertNode(nativeRenderer, newAtom, context);
1487
1451
  }
1488
1452
  context.host = newAtom.nativeNode;
1489
1453
  context.isParent = false;
1490
- const applyRefs = updateNativeNodeProperties(nativeRenderer, newAtom.jsxNode, oldAtom.jsxNode, newAtom.nativeNode, newAtom.isSvg);
1491
- if (newAtom.child) {
1492
- diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, {
1493
- host: newAtom.nativeNode,
1494
- isParent: true,
1495
- rootHost: context.rootHost
1496
- }, 0, 0);
1497
- }
1498
- else if (oldAtom.child) {
1499
- let atom = oldAtom.child;
1500
- nativeRenderer.cleanChildren(oldAtom.nativeNode, oldAtom.isSvg);
1501
- while (atom) {
1502
- cleanView(nativeRenderer, atom, true);
1503
- atom = atom.sibling;
1504
- }
1505
- }
1506
- applyRefs();
1454
+ updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, context);
1507
1455
  };
1508
1456
  }
1509
- function updateComponent(newAtom, reusedAtom, expectIndex, oldIndex, nativeRenderer, context) {
1457
+ function updateComponent(newAtom, reusedAtom, nativeRenderer, context) {
1510
1458
  return function (offset) {
1511
1459
  const component = reusedAtom.jsxNode;
1512
1460
  const newProps = newAtom.jsxNode.props;
@@ -1514,10 +1462,10 @@ function updateComponent(newAtom, reusedAtom, expectIndex, oldIndex, nativeRende
1514
1462
  const newTemplate = component.update(newProps);
1515
1463
  const portalHost = component.instance.$portalHost;
1516
1464
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
1517
- component.$$view = Object.assign({ atom: newAtom }, context);
1465
+ componentViewCache.set(component, Object.assign({ atom: newAtom }, context));
1518
1466
  newAtom.jsxNode = component;
1519
1467
  if (newTemplate === oldTemplate) {
1520
- reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, expectIndex - offset !== oldIndex);
1468
+ reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, newAtom.index - offset !== reusedAtom.index);
1521
1469
  updateView(nativeRenderer, component);
1522
1470
  return;
1523
1471
  }
@@ -1525,12 +1473,12 @@ function updateComponent(newAtom, reusedAtom, expectIndex, oldIndex, nativeRende
1525
1473
  newAtom.child = createChildChain(newTemplate, newAtom.isSvg);
1526
1474
  }
1527
1475
  if (newAtom.child) {
1528
- diff(nativeRenderer, component, newAtom.child, reusedAtom.child, context, expectIndex, oldIndex + offset);
1476
+ diff(nativeRenderer, component, newAtom.child, reusedAtom.child, context);
1529
1477
  }
1530
1478
  else if (reusedAtom.child) {
1531
1479
  let atom = reusedAtom.child;
1532
1480
  while (atom) {
1533
- cleanView(nativeRenderer, atom, false);
1481
+ cleanView(nativeRenderer, atom, true);
1534
1482
  atom = atom.sibling;
1535
1483
  }
1536
1484
  }
@@ -1561,13 +1509,21 @@ function reuseComponentView(nativeRenderer, newAtom, reusedAtom, context, moveVi
1561
1509
  child = child.sibling;
1562
1510
  }
1563
1511
  }
1512
+ function cleanElementChildren(atom, nativeRenderer) {
1513
+ let child = atom.child;
1514
+ nativeRenderer.cleanChildren(atom.nativeNode, atom.isSvg);
1515
+ while (child) {
1516
+ cleanView(nativeRenderer, child, false);
1517
+ child = child.sibling;
1518
+ }
1519
+ }
1564
1520
  function cleanView(nativeRenderer, atom, needClean) {
1565
1521
  if (atom.nativeNode) {
1566
- if (!needClean) {
1522
+ if (needClean) {
1567
1523
  nativeRenderer.remove(atom.nativeNode, atom.isSvg);
1568
- needClean = true;
1524
+ needClean = false;
1569
1525
  }
1570
- if (atom.type === 'element') {
1526
+ if (atom.type === ElementAtomType) {
1571
1527
  const ref = atom.jsxNode.props[refKey];
1572
1528
  applyRefs(ref, atom.nativeNode, false);
1573
1529
  }
@@ -1575,7 +1531,7 @@ function cleanView(nativeRenderer, atom, needClean) {
1575
1531
  let child = atom.child;
1576
1532
  while (child) {
1577
1533
  if (child.jsxNode instanceof Component && child.jsxNode.instance.$portalHost) {
1578
- needClean = false;
1534
+ needClean = true;
1579
1535
  }
1580
1536
  cleanView(nativeRenderer, child, needClean);
1581
1537
  child = child.sibling;
@@ -1588,7 +1544,7 @@ function componentRender(nativeRenderer, component, from, context) {
1588
1544
  const { template, portalHost } = component.render();
1589
1545
  from.child = createChildChain(template, from.isSvg);
1590
1546
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
1591
- component.$$view = Object.assign({ atom: from }, context);
1547
+ componentViewCache.set(component, Object.assign({ atom: from }, context));
1592
1548
  let child = from.child;
1593
1549
  while (child) {
1594
1550
  buildView(nativeRenderer, component, child, context);
@@ -1596,49 +1552,26 @@ function componentRender(nativeRenderer, component, from, context) {
1596
1552
  }
1597
1553
  component.rendered();
1598
1554
  }
1599
- function createChainByJSXComponent(jsxNode, prevAtom, isSvg) {
1600
- const atom = {
1601
- type: 'component',
1602
- jsxNode,
1603
- sibling: null,
1604
- child: null,
1605
- nativeNode: null,
1606
- isSvg
1607
- };
1608
- prevAtom.sibling = atom;
1609
- return atom;
1610
- }
1611
- function createChainByJSXText(jsxNode, prevAtom, isSvg) {
1555
+ function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, isSvg, key) {
1612
1556
  const atom = {
1613
- type: 'text',
1557
+ type,
1558
+ index: prevAtom.index + 1,
1614
1559
  jsxNode,
1615
1560
  sibling: null,
1616
1561
  child: null,
1617
1562
  nativeNode: null,
1618
- isSvg
1619
- };
1620
- prevAtom.sibling = atom;
1621
- return atom;
1622
- }
1623
- function createChainByJSXElement(element, prevAtom, isSvg) {
1624
- isSvg = isSvg || element.type === 'svg';
1625
- const atom = {
1626
- type: 'element',
1627
- jsxNode: element,
1628
- sibling: null,
1629
- child: null,
1630
- nativeNode: null,
1631
- isSvg
1563
+ isSvg,
1564
+ nodeType,
1565
+ key
1632
1566
  };
1633
1567
  prevAtom.sibling = atom;
1634
- atom.child = createChildChain(element.props.children, isSvg);
1635
1568
  return atom;
1636
1569
  }
1637
1570
  function createChainByNode(jsxNode, prevAtom, isSvg) {
1638
1571
  const type = typeof jsxNode;
1639
1572
  if (jsxNode !== null && type !== 'undefined' && type !== 'boolean') {
1640
1573
  if (typeof jsxNode === 'string') {
1641
- return createChainByJSXText(jsxNode, prevAtom, isSvg);
1574
+ return createChainByJSXNode(TextAtomType, jsxNode, jsxNode, prevAtom, isSvg);
1642
1575
  }
1643
1576
  if (Array.isArray(jsxNode)) {
1644
1577
  return createChainByChildren(jsxNode, prevAtom, isSvg);
@@ -1646,13 +1579,14 @@ function createChainByNode(jsxNode, prevAtom, isSvg) {
1646
1579
  if (type === 'object') {
1647
1580
  const nodeType = typeof jsxNode.type;
1648
1581
  if (nodeType === 'string') {
1649
- return createChainByJSXElement(jsxNode, prevAtom, isSvg);
1582
+ return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom, isSvg || jsxNode.type === 'svg', jsxNode.key);
1650
1583
  }
1651
1584
  else if (nodeType === 'function') {
1652
- return createChainByJSXComponent(jsxNode, prevAtom, isSvg);
1585
+ return createChainByJSXNode(ComponentAtomType, jsxNode, jsxNode.type, prevAtom, isSvg, jsxNode.key);
1653
1586
  }
1654
1587
  }
1655
- return createChainByJSXText(String(jsxNode), prevAtom, isSvg);
1588
+ const text = String(jsxNode);
1589
+ return createChainByJSXNode(TextAtomType, text, text, prevAtom, isSvg);
1656
1590
  }
1657
1591
  return prevAtom;
1658
1592
  }
@@ -1663,7 +1597,7 @@ function createChainByChildren(children, prevAtom, isSvg) {
1663
1597
  return prevAtom;
1664
1598
  }
1665
1599
  function createChildChain(template, isSvg) {
1666
- const beforeAtom = { sibling: null };
1600
+ const beforeAtom = { sibling: null, index: -1 };
1667
1601
  createChainByNode(template, beforeAtom, isSvg);
1668
1602
  return beforeAtom.sibling;
1669
1603
  }
@@ -1680,12 +1614,14 @@ function insertNode(nativeRenderer, atom, context) {
1680
1614
  nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.isSvg);
1681
1615
  }
1682
1616
  }
1683
- function createElement(nativeRenderer, vNode, isSvg) {
1684
- const nativeNode = nativeRenderer.createElement(vNode.type, isSvg);
1685
- const props = vNode.props;
1617
+ function createElement(nativeRenderer, atom, parentComponent, context) {
1618
+ const { isSvg, jsxNode } = atom;
1619
+ const nativeNode = nativeRenderer.createElement(jsxNode.type, isSvg);
1620
+ const props = jsxNode.props;
1686
1621
  let bindingRefs;
1687
1622
  for (const key in props) {
1688
1623
  if (key === 'children') {
1624
+ atom.child = createChildChain(jsxNode.props.children, isSvg);
1689
1625
  continue;
1690
1626
  }
1691
1627
  if (key === 'class') {
@@ -1705,7 +1641,7 @@ function createElement(nativeRenderer, vNode, isSvg) {
1705
1641
  if (listenerReg.test(key)) {
1706
1642
  const listener = props[key];
1707
1643
  if (typeof listener === 'function') {
1708
- bindEvent(nativeRenderer, vNode, key, nativeNode, listener, isSvg);
1644
+ nativeRenderer.listen(nativeNode, key, listener, isSvg);
1709
1645
  }
1710
1646
  continue;
1711
1647
  }
@@ -1715,21 +1651,32 @@ function createElement(nativeRenderer, vNode, isSvg) {
1715
1651
  }
1716
1652
  nativeRenderer.setProperty(nativeNode, key, props[key], isSvg);
1717
1653
  }
1718
- return {
1719
- nativeNode,
1720
- applyRefs: () => {
1721
- applyRefs(bindingRefs, nativeNode, true);
1722
- }
1723
- };
1724
- }
1725
- function createTextNode(nativeRenderer, text, isSvg) {
1726
- return nativeRenderer.createTextNode(text, isSvg);
1727
- }
1728
- function updateNativeNodeProperties(nativeRenderer, newVNode, oldVNode, nativeNode, isSvg) {
1654
+ atom.nativeNode = nativeNode;
1655
+ insertNode(nativeRenderer, atom, context);
1656
+ buildElementChildren(atom, nativeRenderer, parentComponent, context);
1657
+ context.host = nativeNode;
1658
+ context.isParent = false;
1659
+ applyRefs(bindingRefs, nativeNode, true);
1660
+ }
1661
+ function createTextNode(nativeRenderer, atom, context) {
1662
+ const nativeNode = nativeRenderer.createTextNode(atom.jsxNode, atom.isSvg);
1663
+ atom.nativeNode = nativeNode;
1664
+ insertNode(nativeRenderer, atom, context);
1665
+ context.host = nativeNode;
1666
+ context.isParent = false;
1667
+ }
1668
+ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, context) {
1669
+ const newVNode = newAtom.jsxNode;
1670
+ const isSvg = newAtom.isSvg;
1671
+ const nativeNode = newAtom.nativeNode;
1672
+ const oldVNode = oldAtom.jsxNode;
1673
+ if (newVNode === oldVNode) {
1674
+ updateElementChildren(newAtom, oldAtom, nativeRenderer, parentComponent, context, isSvg);
1675
+ return;
1676
+ }
1729
1677
  const changes = getObjectChanges(newVNode.props, oldVNode.props);
1730
1678
  let unBindRefs;
1731
1679
  let bindRefs;
1732
- newVNode.on = oldVNode.on;
1733
1680
  for (const [key, value] of changes.remove) {
1734
1681
  if (key === 'children') {
1735
1682
  continue;
@@ -1746,10 +1693,7 @@ function updateNativeNodeProperties(nativeRenderer, newVNode, oldVNode, nativeNo
1746
1693
  }
1747
1694
  if (listenerReg.test(key)) {
1748
1695
  if (typeof value === 'function') {
1749
- const type = key.replace(listenerReg, '').toLowerCase();
1750
- const oldOn = oldVNode.on;
1751
- nativeRenderer.unListen(nativeNode, type, oldOn[type].delegate, isSvg);
1752
- Reflect.deleteProperty(oldOn, type);
1696
+ nativeRenderer.unListen(nativeNode, key, value, isSvg);
1753
1697
  }
1754
1698
  continue;
1755
1699
  }
@@ -1782,8 +1726,8 @@ function updateNativeNodeProperties(nativeRenderer, newVNode, oldVNode, nativeNo
1782
1726
  continue;
1783
1727
  }
1784
1728
  if (listenerReg.test(key)) {
1785
- const listenType = key.replace(listenerReg, '').toLowerCase();
1786
- newVNode.on[listenType].listenFn = newValue;
1729
+ nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
1730
+ nativeRenderer.listen(nativeNode, key, newValue, isSvg);
1787
1731
  continue;
1788
1732
  }
1789
1733
  if (key === refKey) {
@@ -1810,7 +1754,7 @@ function updateNativeNodeProperties(nativeRenderer, newVNode, oldVNode, nativeNo
1810
1754
  }
1811
1755
  if (listenerReg.test(key)) {
1812
1756
  if (typeof value === 'function') {
1813
- bindEvent(nativeRenderer, newVNode, key, nativeNode, value, isSvg);
1757
+ nativeRenderer.listen(nativeNode, key, value, isSvg);
1814
1758
  }
1815
1759
  continue;
1816
1760
  }
@@ -1820,10 +1764,36 @@ function updateNativeNodeProperties(nativeRenderer, newVNode, oldVNode, nativeNo
1820
1764
  }
1821
1765
  nativeRenderer.setProperty(nativeNode, key, value, isSvg);
1822
1766
  }
1823
- return () => {
1824
- applyRefs(unBindRefs, nativeNode, false);
1825
- applyRefs(bindRefs, nativeNode, true);
1826
- };
1767
+ updateElementChildren(newAtom, oldAtom, nativeRenderer, parentComponent, context, isSvg);
1768
+ applyRefs(unBindRefs, nativeNode, false);
1769
+ applyRefs(bindRefs, nativeNode, true);
1770
+ }
1771
+ function updateElementChildren(newAtom, oldAtom, nativeRenderer, parentComponent, context, isSvg) {
1772
+ /**
1773
+ * 不能仅依赖 children 是否相等的判断来确定是否要继续向下 diff
1774
+ * 如:
1775
+ * ```tsx
1776
+ * <Comp>
1777
+ * <div>
1778
+ * {props.children}
1779
+ * </div>
1780
+ * </Comp>
1781
+ * ```
1782
+ * 其中当 Comp 产生变化时,children 来自父组件,这时 children 是相等的,
1783
+ * 但,children 内可能有子组件也发生了变化,如果不继续 diff,那么,子组件
1784
+ * 的视图更新将不会发生
1785
+ */
1786
+ newAtom.child = createChildChain(newAtom.jsxNode.props.children, isSvg);
1787
+ if (!newAtom.child) {
1788
+ cleanElementChildren(oldAtom, nativeRenderer);
1789
+ }
1790
+ else {
1791
+ diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, {
1792
+ host: newAtom.nativeNode,
1793
+ isParent: true,
1794
+ rootHost: context.rootHost
1795
+ });
1796
+ }
1827
1797
  }
1828
1798
  function applyRefs(refs, nativeNode, binding) {
1829
1799
  if (refs) {
@@ -1835,21 +1805,6 @@ function applyRefs(refs, nativeNode, binding) {
1835
1805
  }
1836
1806
  }
1837
1807
  }
1838
- function bindEvent(nativeRenderer, vNode, key, nativeNode, listenFn, isSvg) {
1839
- let on = vNode.on;
1840
- if (!on) {
1841
- vNode.on = on = {};
1842
- }
1843
- const type = key.replace(listenerReg, '').toLowerCase();
1844
- const delegateObj = {
1845
- delegate(...args) {
1846
- return delegateObj.listenFn.apply(this, args);
1847
- },
1848
- listenFn
1849
- };
1850
- on[type] = delegateObj;
1851
- nativeRenderer.listen(nativeNode, type, delegateObj.delegate, isSvg);
1852
- }
1853
1808
 
1854
1809
  /**
1855
1810
  * Viewfly 根组件,用于实现组件状态更新事件通知