@tarojs/router 3.7.0-alpha.2 → 3.7.0-alpha.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createBrowserHistory, createHashHistory, Action, parsePath } from 'history';
2
- import { Current, incrementId, eventCenter, createPageConfig, hooks, stringify, requestAnimationFrame } from '@tarojs/runtime';
2
+ import { Current, eventCenter, incrementId, createPageConfig, hooks, stringify, requestAnimationFrame as requestAnimationFrame$1 } from '@tarojs/runtime';
3
3
  import MobileDetect from 'mobile-detect';
4
4
  import queryString from 'query-string';
5
5
  import { defineCustomElementTaroTabbar } from '@tarojs/components/dist/components';
@@ -31,65 +31,6 @@ function __awaiter(thisArg, _arguments, P, generator) {
31
31
  });
32
32
  }
33
33
 
34
- // export const removeLeadingSlash = (str = '') => str.replace(/^\.?\//, '')
35
- // export const removeTrailingSearch = (str = '') => str.replace(/\?[\s\S]*$/, '')
36
- const addLeadingSlash = (url = '') => (url.charAt(0) === '/' ? url : '/' + url);
37
- const hasBasename = (path = '', prefix = '') => new RegExp('^' + prefix + '(\\/|\\?|#|$)', 'i').test(path) || path === prefix;
38
- const stripBasename = (path = '', prefix = '') => hasBasename(path, prefix) ? path.substring(prefix.length) : path;
39
- const stripTrailing = (str = '') => str.replace(/[?#][\s\S]*$/, '');
40
- const getHomePage = (path = '', basename = '', customRoutes = {}, entryPagePath = '') => {
41
- var _a;
42
- const routePath = addLeadingSlash(stripBasename(path, basename));
43
- const alias = ((_a = Object.entries(customRoutes).find(([key]) => key === routePath)) === null || _a === void 0 ? void 0 : _a[1]) || routePath;
44
- return entryPagePath || (typeof alias === 'string' ? alias : alias[0]) || basename;
45
- };
46
- const getCurrentPage = (routerMode = 'hash', basename = '/') => {
47
- const pagePath = routerMode === 'hash'
48
- ? location.hash.slice(1).split('?')[0]
49
- : location.pathname;
50
- return addLeadingSlash(stripBasename(pagePath, basename));
51
- };
52
- class RoutesAlias {
53
- constructor() {
54
- this.conf = [];
55
- this.getConfig = (url = '') => {
56
- const customRoute = this.conf.filter((arr) => {
57
- return arr.includes(url);
58
- });
59
- return customRoute[0];
60
- };
61
- this.getOrigin = (url = '') => {
62
- var _a;
63
- return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[0]) || url;
64
- };
65
- this.getAlias = (url = '') => {
66
- var _a;
67
- return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[1]) || url;
68
- };
69
- this.getAll = (url = '') => {
70
- return this.conf
71
- .filter((arr) => arr.includes(url))
72
- .reduceRight((p, a) => {
73
- p.unshift(a[1]);
74
- return p;
75
- }, []);
76
- };
77
- }
78
- set(customRoutes = {}) {
79
- for (let key in customRoutes) {
80
- const path = customRoutes[key];
81
- key = addLeadingSlash(key);
82
- if (typeof path === 'string') {
83
- this.conf.push([key, addLeadingSlash(path)]);
84
- }
85
- else if ((path === null || path === void 0 ? void 0 : path.length) > 0) {
86
- this.conf.push(...path.map(p => [key, addLeadingSlash(p)]));
87
- }
88
- }
89
- }
90
- }
91
- const routesAlias = new RoutesAlias();
92
-
93
34
  class RouterConfig {
94
35
  static set config(e) {
95
36
  this.__config = e;
@@ -108,7 +49,7 @@ class RouterConfig {
108
49
  }
109
50
  static get customRoutes() { return this.router.customRoutes || {}; }
110
51
  static isPage(url = '') {
111
- return this.pages.findIndex(e => addLeadingSlash(e) === url) !== -1;
52
+ return this.pages.findIndex(e => prependBasename(e) === url) !== -1;
112
53
  }
113
54
  }
114
55
 
@@ -147,7 +88,7 @@ class MpaHistory {
147
88
  return url;
148
89
  }
149
90
  push(to, _state = {}) {
150
- window.location.pathname = this.parseUrl(to);
91
+ window.location.assign(this.parseUrl(to));
151
92
  // this.pushState(_state, '', this.parseUrl(to))
152
93
  }
153
94
  replace(to, _state = {}) {
@@ -292,6 +233,65 @@ class Stacks {
292
233
  }
293
234
  const stacks = new Stacks();
294
235
 
236
+ // export const removeLeadingSlash = (str = '') => str.replace(/^\.?\//, '')
237
+ // export const removeTrailingSearch = (str = '') => str.replace(/\?[\s\S]*$/, '')
238
+ const addLeadingSlash = (url = '') => (url.charAt(0) === '/' ? url : '/' + url);
239
+ const hasBasename = (path = '', prefix = '') => new RegExp('^' + prefix + '(\\/|\\?|#|$)', 'i').test(path) || path === prefix;
240
+ const stripBasename = (path = '', prefix = '') => hasBasename(path, prefix) ? path.substring(prefix.length) : path;
241
+ const stripTrailing = (str = '') => str.replace(/[?#][\s\S]*$/, '');
242
+ const getHomePage = (path = '', basename = '', customRoutes = {}, entryPagePath = '') => {
243
+ var _a;
244
+ const routePath = addLeadingSlash(stripBasename(path, basename));
245
+ const alias = ((_a = Object.entries(customRoutes).find(([key]) => key === routePath)) === null || _a === void 0 ? void 0 : _a[1]) || routePath;
246
+ return entryPagePath || (typeof alias === 'string' ? alias : alias[0]) || basename;
247
+ };
248
+ const getCurrentPage = (routerMode = 'hash', basename = '/') => {
249
+ const pagePath = routerMode === 'hash'
250
+ ? location.hash.slice(1).split('?')[0]
251
+ : location.pathname;
252
+ return addLeadingSlash(stripBasename(pagePath, basename));
253
+ };
254
+ class RoutesAlias {
255
+ constructor() {
256
+ this.conf = [];
257
+ this.getConfig = (url = '') => {
258
+ const customRoute = this.conf.filter((arr) => {
259
+ return arr.includes(url);
260
+ });
261
+ return customRoute[0];
262
+ };
263
+ this.getOrigin = (url = '') => {
264
+ var _a;
265
+ return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[0]) || url;
266
+ };
267
+ this.getAlias = (url = '') => {
268
+ var _a;
269
+ return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[1]) || url;
270
+ };
271
+ this.getAll = (url = '') => {
272
+ return this.conf
273
+ .filter((arr) => arr.includes(url))
274
+ .reduceRight((p, a) => {
275
+ p.unshift(a[1]);
276
+ return p;
277
+ }, []);
278
+ };
279
+ }
280
+ set(customRoutes = {}) {
281
+ for (let key in customRoutes) {
282
+ const path = customRoutes[key];
283
+ key = addLeadingSlash(key);
284
+ if (typeof path === 'string') {
285
+ this.conf.push([key, addLeadingSlash(path)]);
286
+ }
287
+ else if ((path === null || path === void 0 ? void 0 : path.length) > 0) {
288
+ this.conf.push(...path.map(p => [key, addLeadingSlash(p)]));
289
+ }
290
+ }
291
+ }
292
+ }
293
+ const routesAlias = new RoutesAlias();
294
+
295
295
  function processNavigateUrl(option) {
296
296
  var _a;
297
297
  const pathPieces = parsePath(option.url);
@@ -345,7 +345,12 @@ function navigate(option, method) {
345
345
  }
346
346
  else if (method === 'navigateBack') {
347
347
  stacks.delta = option.delta;
348
- history.go(-option.delta);
348
+ if (stacks.length > option.delta) {
349
+ history.go(-option.delta);
350
+ }
351
+ else {
352
+ history.go(1 - stacks.length);
353
+ }
349
354
  }
350
355
  }
351
356
  catch (error) {
@@ -430,11 +435,11 @@ function bindPageResize(page) {
430
435
 
431
436
  const pageScrollFn = {};
432
437
  let pageDOM = window;
433
- function bindPageScroll(page, pageEl, distance = 50) {
438
+ function bindPageScroll(page, scrollEl, distance = 50) {
434
439
  var _a;
435
440
  const pagePath = (page ? page === null || page === void 0 ? void 0 : page.path : (_a = Current.router) === null || _a === void 0 ? void 0 : _a.path);
436
- pageScrollFn[pagePath] && pageEl.removeEventListener('scroll', pageScrollFn[pagePath]);
437
- pageDOM = pageEl;
441
+ pageScrollFn[pagePath] && scrollEl.removeEventListener('scroll', pageScrollFn[pagePath]);
442
+ pageDOM = scrollEl;
438
443
  let isReachBottom = false;
439
444
  pageScrollFn[pagePath] = function () {
440
445
  var _a;
@@ -462,6 +467,78 @@ function getOffset() {
462
467
  }
463
468
  }
464
469
 
470
+ /**
471
+ * 插入页面动画需要的样式
472
+ */
473
+ function loadAnimateStyle(ms = 300) {
474
+ const css = `
475
+ .taro_router > .taro_page {
476
+ position: absolute;
477
+ left: 0;
478
+ top: 0;
479
+ width: 100%;
480
+ height: 100%;
481
+ background-color: #fff;
482
+ transform: translate(100%, 0);
483
+ transition: transform ${ms}ms;
484
+ z-index: 0;
485
+ }
486
+
487
+ .taro_router > .taro_page.taro_tabbar_page,
488
+ .taro_router > .taro_page.taro_page_show.taro_page_stationed {
489
+ transform: none;
490
+ }
491
+
492
+ .taro_router > .taro_page.taro_page_show {
493
+ transform: translate(0, 0);
494
+ }
495
+
496
+ .taro_page_shade,
497
+ .taro_router > .taro_page.taro_page_show.taro_page_stationed:not(.taro_page_shade):not(.taro_tabbar_page):not(:last-child) {
498
+ display: none;
499
+ }`;
500
+ addStyle(css);
501
+ }
502
+ /**
503
+ * 插入路由相关样式
504
+ */
505
+ function loadRouterStyle(usingWindowScroll) {
506
+ const css = `
507
+ .taro_router {
508
+ position: relative;
509
+ width: 100%;
510
+ height: 100%;
511
+ }
512
+
513
+ .taro_page {
514
+ width: 100%;
515
+ height: 100%;
516
+ ${usingWindowScroll ? '' : `
517
+ overflow-x: hidden;
518
+ overflow-y: scroll;
519
+ max-height: 100vh;
520
+ `}
521
+ }
522
+
523
+ .taro-tabbar__container > .taro-tabbar__panel {
524
+ overflow: hidden;
525
+ }
526
+
527
+ .taro-tabbar__container > .taro-tabbar__panel > .taro_page.taro_tabbar_page {
528
+ max-height: calc(100vh - var(--taro-tabbar-height) - constant(safe-area-inset-bottom));
529
+ max-height: calc(100vh - var(--taro-tabbar-height) - env(safe-area-inset-bottom));
530
+ }
531
+ `;
532
+ addStyle(css);
533
+ }
534
+ function addStyle(css) {
535
+ if (!css)
536
+ return;
537
+ const style = document.createElement('style');
538
+ style.innerHTML = css;
539
+ document.getElementsByTagName('head')[0].appendChild(style);
540
+ }
541
+
465
542
  // @ts-nocheck
466
543
  function initTabbar(config) {
467
544
  if (config.tabBar == null) {
@@ -522,6 +599,17 @@ class MultiPageHandler {
522
599
  return !!pagePath && this.tabBarList.some(t => t.pagePath === pagePath);
523
600
  }
524
601
  get search() { return location.search.substr(1); }
602
+ get usingWindowScroll() {
603
+ var _a;
604
+ let usingWindowScroll = true;
605
+ if (typeof ((_a = this.pageConfig) === null || _a === void 0 ? void 0 : _a.usingWindowScroll) === 'boolean') {
606
+ usingWindowScroll = this.pageConfig.usingWindowScroll;
607
+ }
608
+ const win = window;
609
+ win.__taroAppConfig || (win.__taroAppConfig = {});
610
+ win.__taroAppConfig.usingWindowScroll = usingWindowScroll;
611
+ return usingWindowScroll;
612
+ }
525
613
  getQuery(search = '', options = {}) {
526
614
  search = search ? `${search}&${this.search}` : this.search;
527
615
  const query = search
@@ -531,6 +619,7 @@ class MultiPageHandler {
531
619
  }
532
620
  mount() {
533
621
  setHistoryMode(this.routerMode, this.router.basename);
622
+ loadRouterStyle(this.usingWindowScroll);
534
623
  const appId = this.appId;
535
624
  let app = document.getElementById(appId);
536
625
  let isPosition = true;
@@ -567,7 +656,20 @@ class MultiPageHandler {
567
656
  const pageEl = this.getPageContainer(page);
568
657
  if (pageEl && !(pageEl === null || pageEl === void 0 ? void 0 : pageEl['__isReady'])) {
569
658
  const el = pageEl.firstElementChild;
570
- (_a = el === null || el === void 0 ? void 0 : el['componentOnReady']) === null || _a === void 0 ? void 0 : _a.call(el);
659
+ const componentOnReady = el === null || el === void 0 ? void 0 : el['componentOnReady'];
660
+ if (componentOnReady) {
661
+ componentOnReady === null || componentOnReady === void 0 ? void 0 : componentOnReady().then(() => {
662
+ requestAnimationFrame(() => {
663
+ var _a;
664
+ (_a = page.onReady) === null || _a === void 0 ? void 0 : _a.call(page);
665
+ pageEl['__isReady'] = true;
666
+ });
667
+ });
668
+ }
669
+ else {
670
+ (_a = page.onReady) === null || _a === void 0 ? void 0 : _a.call(page);
671
+ pageEl['__isReady'] = true;
672
+ }
571
673
  onLoad && (pageEl['__page'] = page);
572
674
  }
573
675
  }
@@ -577,11 +679,14 @@ class MultiPageHandler {
577
679
  return;
578
680
  (_a = page.onLoad) === null || _a === void 0 ? void 0 : _a.call(page, this.getQuery('', page.options), () => {
579
681
  var _a;
580
- const pageEl = this.getPageContainer(page);
581
- this.isTabBar && (pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.add('taro_tabbar_page'));
682
+ if (this.isTabBar) {
683
+ const pageEl = this.getPageContainer(page);
684
+ pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.add('taro_tabbar_page');
685
+ }
582
686
  this.onReady(page, true);
583
687
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
584
- this.bindPageEvents(page, pageEl, pageConfig);
688
+ this.bindPageEvents(page, pageConfig);
689
+ this.triggerRouterChange();
585
690
  });
586
691
  }
587
692
  getPageContainer(page) {
@@ -595,17 +700,33 @@ class MultiPageHandler {
595
700
  ? document.querySelector(`.taro_page#${id}`)
596
701
  : document.querySelector('.taro_page') ||
597
702
  document.querySelector('.taro_router'));
598
- return el || window;
703
+ return el;
704
+ }
705
+ getScrollingElement(page) {
706
+ if (this.usingWindowScroll)
707
+ return window;
708
+ return this.getPageContainer(page) || window;
599
709
  }
600
- bindPageEvents(page, pageEl, config = {}) {
710
+ bindPageEvents(page, config = {}) {
601
711
  var _a;
602
- if (!pageEl) {
603
- pageEl = this.getPageContainer();
604
- }
712
+ const scrollEl = this.getScrollingElement(page);
605
713
  const distance = config.onReachBottomDistance || ((_a = this.config.window) === null || _a === void 0 ? void 0 : _a.onReachBottomDistance) || 50;
606
- bindPageScroll(page, pageEl, distance);
714
+ bindPageScroll(page, scrollEl, distance);
607
715
  bindPageResize(page);
608
716
  }
717
+ triggerRouterChange() {
718
+ /**
719
+ * @tarojs/runtime 中生命周期跑在 promise 中,所以这里需要 setTimeout 延迟事件调用
720
+ * TODO 考虑将生命周期返回 Promise,用于处理相关事件调用顺序
721
+ */
722
+ setTimeout(() => {
723
+ eventCenter.trigger('__afterTaroRouterChange', {
724
+ toLocation: {
725
+ path: this.pathname
726
+ }
727
+ });
728
+ }, 0);
729
+ }
609
730
  }
610
731
 
611
732
  const createStampId$1 = incrementId();
@@ -621,6 +742,9 @@ const launchStampId$1 = createStampId$1();
621
742
  function createMultiRouter(app, config, framework) {
622
743
  var _a, _b, _c, _d, _e, _f;
623
744
  return __awaiter(this, void 0, void 0, function* () {
745
+ if (typeof app.onUnhandledRejection === 'function') {
746
+ window.addEventListener('unhandledrejection', app.onUnhandledRejection);
747
+ }
624
748
  RouterConfig.config = config;
625
749
  const handler = new MultiPageHandler(config);
626
750
  const launchParam = {
@@ -663,48 +787,13 @@ function createMultiRouter(app, config, framework) {
663
787
  const loadConfig = Object.assign({}, pageConfig);
664
788
  delete loadConfig['path'];
665
789
  delete loadConfig['load'];
666
- const page = createPageConfig(enablePullDownRefresh ? hooks.call('createPullDownComponent', el, location.pathname, framework, handler.PullDownRefresh) : el, pathName + stringify(launchParam), {}, loadConfig);
790
+ const page = createPageConfig(enablePullDownRefresh ? hooks.call('createPullDownComponent', el, pathName, framework, handler.PullDownRefresh) : el, pathName + stringify(launchParam), {}, loadConfig);
667
791
  handler.load(page, pageConfig);
668
792
  (_f = app.onShow) === null || _f === void 0 ? void 0 : _f.call(app, launchParam);
669
793
  });
670
794
  }
671
795
 
672
- /**
673
- * 插入页面动画需要的样式
674
- */
675
- function loadAnimateStyle(ms = 300) {
676
- const css = `
677
- .taro_router .taro_page {
678
- position: absolute;
679
- left: 0;
680
- top: 0;
681
- width: 100%;
682
- height: 100%;
683
- background-color: #fff;
684
- transform: translate(100%, 0);
685
- transition: transform ${ms}ms;
686
- z-index: 0;
687
- }
688
-
689
- .taro_router .taro_page.taro_tabbar_page,
690
- .taro_router .taro_page.taro_page_show.taro_page_stationed {
691
- transform: none;
692
- }
693
-
694
- .taro_router .taro_page.taro_page_show {
695
- transform: translate(0, 0);
696
- }`;
697
- const style = document.createElement('style');
698
- style.innerHTML = css;
699
- document.getElementsByTagName('head')[0].appendChild(style);
700
- }
701
-
702
796
  /* eslint-disable dot-notation */
703
- function setDisplay(el, type = '') {
704
- if (el) {
705
- el.style.display = type;
706
- }
707
- }
708
797
  class PageHandler {
709
798
  constructor(config) {
710
799
  this.defaultAnimation = { duration: 300, delay: 50 };
@@ -784,6 +873,17 @@ class PageHandler {
784
873
  }
785
874
  return search.substring(1);
786
875
  }
876
+ get usingWindowScroll() {
877
+ var _a;
878
+ let usingWindowScroll = false;
879
+ if (typeof ((_a = this.pageConfig) === null || _a === void 0 ? void 0 : _a.usingWindowScroll) === 'boolean') {
880
+ usingWindowScroll = this.pageConfig.usingWindowScroll;
881
+ }
882
+ const win = window;
883
+ win.__taroAppConfig || (win.__taroAppConfig = {});
884
+ win.__taroAppConfig.usingWindowScroll = usingWindowScroll;
885
+ return usingWindowScroll;
886
+ }
787
887
  getQuery(stamp = '', search = '', options = {}) {
788
888
  search = search ? `${search}&${this.search}` : this.search;
789
889
  const query = search
@@ -794,7 +894,9 @@ class PageHandler {
794
894
  }
795
895
  mount() {
796
896
  setHistoryMode(this.routerMode, this.router.basename);
897
+ this.pathname = history.location.pathname;
797
898
  this.animation && loadAnimateStyle(this.animationDuration);
899
+ loadRouterStyle(this.usingWindowScroll);
798
900
  const appId = this.appId;
799
901
  let app = document.getElementById(appId);
800
902
  let isPosition = true;
@@ -834,7 +936,7 @@ class PageHandler {
834
936
  const componentOnReady = el === null || el === void 0 ? void 0 : el['componentOnReady'];
835
937
  if (componentOnReady) {
836
938
  componentOnReady === null || componentOnReady === void 0 ? void 0 : componentOnReady().then(() => {
837
- requestAnimationFrame(() => {
939
+ requestAnimationFrame$1(() => {
838
940
  var _a;
839
941
  (_a = page.onReady) === null || _a === void 0 ? void 0 : _a.call(page);
840
942
  pageEl['__isReady'] = true;
@@ -857,11 +959,12 @@ class PageHandler {
857
959
  const param = this.getQuery(stampId, '', page.options);
858
960
  let pageEl = this.getPageContainer(page);
859
961
  if (pageEl) {
860
- setDisplay(pageEl);
962
+ pageEl.classList.remove('taro_page_shade');
861
963
  this.isTabBar(this.pathname) && pageEl.classList.add('taro_tabbar_page');
862
964
  this.addAnimation(pageEl, pageNo === 0);
863
965
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
864
- this.bindPageEvents(page, pageEl, pageConfig);
966
+ this.bindPageEvents(page, pageConfig);
967
+ this.triggerRouterChange();
865
968
  }
866
969
  else {
867
970
  (_b = page.onLoad) === null || _b === void 0 ? void 0 : _b.call(page, param, () => {
@@ -871,7 +974,8 @@ class PageHandler {
871
974
  this.addAnimation(pageEl, pageNo === 0);
872
975
  this.onReady(page, true);
873
976
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
874
- this.bindPageEvents(page, pageEl, pageConfig);
977
+ this.bindPageEvents(page, pageConfig);
978
+ this.triggerRouterChange();
875
979
  });
876
980
  }
877
981
  }
@@ -891,10 +995,14 @@ class PageHandler {
891
995
  const pageEl = this.getPageContainer(page);
892
996
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_stationed');
893
997
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_show');
998
+ if (pageEl) {
999
+ pageEl.style.zIndex = '1';
1000
+ }
894
1001
  this.unloadTimer = setTimeout(() => {
895
1002
  var _a, _b;
896
1003
  this.unloadTimer = null;
897
1004
  (_b = (_a = this.lastUnloadPage) === null || _a === void 0 ? void 0 : _a.onUnload) === null || _b === void 0 ? void 0 : _b.call(_a);
1005
+ eventCenter.trigger('__taroPageOnShowAfterDestroyed');
898
1006
  }, this.animationDuration);
899
1007
  }
900
1008
  else {
@@ -902,6 +1010,9 @@ class PageHandler {
902
1010
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_stationed');
903
1011
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_show');
904
1012
  (_c = page === null || page === void 0 ? void 0 : page.onUnload) === null || _c === void 0 ? void 0 : _c.call(page);
1013
+ setTimeout(() => {
1014
+ eventCenter.trigger('__taroPageOnShowAfterDestroyed');
1015
+ }, 0);
905
1016
  }
906
1017
  if (delta >= 1)
907
1018
  this.unload(stacks.last, delta);
@@ -913,10 +1024,11 @@ class PageHandler {
913
1024
  const param = this.getQuery(page['$taroParams']['stamp'], '', page.options);
914
1025
  let pageEl = this.getPageContainer(page);
915
1026
  if (pageEl) {
916
- setDisplay(pageEl);
1027
+ pageEl.classList.remove('taro_page_shade');
917
1028
  this.addAnimation(pageEl, pageNo === 0);
918
1029
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
919
- this.bindPageEvents(page, pageEl, pageConfig);
1030
+ this.bindPageEvents(page, pageConfig);
1031
+ this.triggerRouterChange();
920
1032
  }
921
1033
  else {
922
1034
  (_b = page.onLoad) === null || _b === void 0 ? void 0 : _b.call(page, param, () => {
@@ -925,7 +1037,8 @@ class PageHandler {
925
1037
  this.addAnimation(pageEl, pageNo === 0);
926
1038
  this.onReady(page, false);
927
1039
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
928
- this.bindPageEvents(page, pageEl, pageConfig);
1040
+ this.bindPageEvents(page, pageConfig);
1041
+ this.triggerRouterChange();
929
1042
  });
930
1043
  }
931
1044
  }
@@ -939,12 +1052,12 @@ class PageHandler {
939
1052
  if (this.hideTimer) {
940
1053
  clearTimeout(this.hideTimer);
941
1054
  this.hideTimer = null;
942
- setDisplay(this.lastHidePage, 'none');
1055
+ pageEl.classList.add('taro_page_shade');
943
1056
  }
944
1057
  this.lastHidePage = pageEl;
945
1058
  this.hideTimer = setTimeout(() => {
946
1059
  this.hideTimer = null;
947
- setDisplay(this.lastHidePage, 'none');
1060
+ pageEl.classList.add('taro_page_shade');
948
1061
  }, this.animationDuration + this.animationDelay);
949
1062
  (_a = page.onHide) === null || _a === void 0 ? void 0 : _a.call(page);
950
1063
  }
@@ -979,23 +1092,42 @@ class PageHandler {
979
1092
  ? document.querySelector(`.taro_page#${id}`)
980
1093
  : document.querySelector('.taro_page') ||
981
1094
  document.querySelector('.taro_router'));
982
- return el || window;
1095
+ return el;
983
1096
  }
984
- bindPageEvents(page, pageEl, config = {}) {
1097
+ getScrollingElement(page) {
1098
+ if (this.usingWindowScroll)
1099
+ return window;
1100
+ return this.getPageContainer(page) || window;
1101
+ }
1102
+ bindPageEvents(page, config = {}) {
985
1103
  var _a;
986
- if (!pageEl) {
987
- pageEl = this.getPageContainer();
988
- }
1104
+ const scrollEl = this.getScrollingElement(page);
989
1105
  const distance = config.onReachBottomDistance || ((_a = this.config.window) === null || _a === void 0 ? void 0 : _a.onReachBottomDistance) || 50;
990
- bindPageScroll(page, pageEl, distance);
1106
+ bindPageScroll(page, scrollEl, distance);
991
1107
  bindPageResize(page);
992
1108
  }
1109
+ triggerRouterChange() {
1110
+ /**
1111
+ * @tarojs/runtime 中生命周期跑在 promise 中,所以这里需要 setTimeout 延迟事件调用
1112
+ * TODO 考虑将生命周期返回 Promise,用于处理相关事件调用顺序
1113
+ */
1114
+ setTimeout(() => {
1115
+ eventCenter.trigger('__afterTaroRouterChange', {
1116
+ toLocation: {
1117
+ path: this.pathname
1118
+ }
1119
+ });
1120
+ }, 0);
1121
+ }
993
1122
  }
994
1123
 
995
1124
  const createStampId = incrementId();
996
1125
  let launchStampId = createStampId();
997
1126
  function createRouter(app, config, framework) {
998
1127
  var _a, _b;
1128
+ if (typeof app.onUnhandledRejection === 'function') {
1129
+ window.addEventListener('unhandledrejection', app.onUnhandledRejection);
1130
+ }
999
1131
  RouterConfig.config = config;
1000
1132
  const handler = new PageHandler(config);
1001
1133
  routesAlias.set(handler.router.customRoutes);
@@ -1020,8 +1152,10 @@ function createRouter(app, config, framework) {
1020
1152
  (_a = app.onLaunch) === null || _a === void 0 ? void 0 : _a.call(app, launchParam);
1021
1153
  app.onError && window.addEventListener('error', e => { var _a; return (_a = app.onError) === null || _a === void 0 ? void 0 : _a.call(app, e.message); });
1022
1154
  const render = ({ location, action }) => __awaiter(this, void 0, void 0, function* () {
1023
- var _c, _d, _e, _f, _g;
1155
+ var _c, _d, _e, _f, _g, _h;
1024
1156
  handler.pathname = decodeURI(location.pathname);
1157
+ if ((_c = window.__taroAppConfig) === null || _c === void 0 ? void 0 : _c.usingWindowScroll)
1158
+ window.scrollTo(0, 0);
1025
1159
  eventCenter.trigger('__taroRouterChange', {
1026
1160
  toLocation: {
1027
1161
  path: handler.pathname
@@ -1034,9 +1168,13 @@ function createRouter(app, config, framework) {
1034
1168
  }
1035
1169
  catch (error) {
1036
1170
  if (error.status === 404) {
1037
- (_c = app.onPageNotFound) === null || _c === void 0 ? void 0 : _c.call(app, {
1038
- path: handler.pathname
1039
- });
1171
+ const notFoundEvent = {
1172
+ isEntryPage: stacks.length === 0,
1173
+ path: handler.pathname,
1174
+ query: handler.getQuery(createStampId()),
1175
+ };
1176
+ (_d = app.onPageNotFound) === null || _d === void 0 ? void 0 : _d.call(app, notFoundEvent);
1177
+ eventCenter.trigger('__taroRouterNotFound', notFoundEvent);
1040
1178
  }
1041
1179
  else if (/Loading hot update .* failed./.test(error.message)) {
1042
1180
  // NOTE: webpack5 与 prebundle 搭配使用时,开发环境下初次启动时偶发错误,由于 HMR 加载 chunk hash 错误,导致热更新失败
@@ -1049,16 +1187,16 @@ function createRouter(app, config, framework) {
1049
1187
  if (!element)
1050
1188
  return;
1051
1189
  const pageConfig = handler.pageConfig;
1052
- let enablePullDownRefresh = ((_d = config === null || config === void 0 ? void 0 : config.window) === null || _d === void 0 ? void 0 : _d.enablePullDownRefresh) || false;
1190
+ let enablePullDownRefresh = ((_e = config === null || config === void 0 ? void 0 : config.window) === null || _e === void 0 ? void 0 : _e.enablePullDownRefresh) || false;
1053
1191
  if (pageConfig) {
1054
- setTitle((_e = pageConfig.navigationBarTitleText) !== null && _e !== void 0 ? _e : document.title);
1192
+ setTitle((_f = pageConfig.navigationBarTitleText) !== null && _f !== void 0 ? _f : document.title);
1055
1193
  if (typeof pageConfig.enablePullDownRefresh === 'boolean') {
1056
1194
  enablePullDownRefresh = pageConfig.enablePullDownRefresh;
1057
1195
  }
1058
1196
  }
1059
1197
  const currentPage = Current.page;
1060
1198
  const pathname = handler.pathname;
1061
- const methodName = (_f = stacks.method) !== null && _f !== void 0 ? _f : '';
1199
+ const methodName = (_g = stacks.method) !== null && _g !== void 0 ? _g : '';
1062
1200
  const cacheTabs = stacks.getTabs();
1063
1201
  let shouldLoad = false;
1064
1202
  stacks.method = '';
@@ -1083,11 +1221,11 @@ function createRouter(app, config, framework) {
1083
1221
  else if (stacks.length > 0) {
1084
1222
  const firstIns = stacks.getItem(0);
1085
1223
  if (handler.isTabBar(firstIns.path)) {
1086
- handler.unload(currentPage, stacks.length - 1);
1224
+ handler.unload(currentPage, stacks.length - 1, true);
1087
1225
  stacks.pushTab(firstIns.path.split('?')[0]);
1088
1226
  }
1089
1227
  else {
1090
- handler.unload(currentPage, stacks.length);
1228
+ handler.unload(currentPage, stacks.length, true);
1091
1229
  }
1092
1230
  }
1093
1231
  if (cacheTabs[handler.pathname]) {
@@ -1104,7 +1242,9 @@ function createRouter(app, config, framework) {
1104
1242
  if (currentPage !== stacks.getItem(prevIndex)) {
1105
1243
  handler.unload(currentPage, delta, prevIndex > -1);
1106
1244
  if (prevIndex > -1) {
1107
- handler.show(stacks.getItem(prevIndex), pageConfig, prevIndex);
1245
+ eventCenter.once('__taroPageOnShowAfterDestroyed', () => {
1246
+ handler.show(stacks.getItem(prevIndex), pageConfig, prevIndex);
1247
+ });
1108
1248
  }
1109
1249
  else {
1110
1250
  shouldLoad = true;
@@ -1122,7 +1262,7 @@ function createRouter(app, config, framework) {
1122
1262
  shouldLoad = true;
1123
1263
  }
1124
1264
  if (shouldLoad || stacks.length < 1) {
1125
- const el = (_g = element.default) !== null && _g !== void 0 ? _g : element;
1265
+ const el = (_h = element.default) !== null && _h !== void 0 ? _h : element;
1126
1266
  const loadConfig = Object.assign({}, pageConfig);
1127
1267
  const stacksIndex = stacks.length;
1128
1268
  delete loadConfig['path'];
@@ -1135,16 +1275,11 @@ function createRouter(app, config, framework) {
1135
1275
  else {
1136
1276
  pageStampId = createStampId();
1137
1277
  }
1138
- const page = createPageConfig(enablePullDownRefresh ? hooks.call('createPullDownComponent', el, location.pathname, framework, handler.PullDownRefresh) : el, pathname + stringify(handler.getQuery(pageStampId)), {}, loadConfig);
1278
+ const page = createPageConfig(enablePullDownRefresh ? hooks.call('createPullDownComponent', el, pathname, framework, handler.PullDownRefresh, pageStampId) : el, pathname + stringify(handler.getQuery(pageStampId)), {}, loadConfig);
1139
1279
  if (params)
1140
1280
  page.options = params;
1141
1281
  handler.load(page, pageConfig, pageStampId, stacksIndex);
1142
1282
  }
1143
- eventCenter.trigger('__afterTaroRouterChange', {
1144
- toLocation: {
1145
- path: handler.pathname
1146
- }
1147
- });
1148
1283
  });
1149
1284
  const routePath = addLeadingSlash(stripBasename(history.location.pathname, handler.basename));
1150
1285
  if (routePath === '/') {