@tarojs/router 3.7.0-alpha.2 → 3.7.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.
package/dist/index.cjs.js CHANGED
@@ -41,65 +41,6 @@ function __awaiter(thisArg, _arguments, P, generator) {
41
41
  });
42
42
  }
43
43
 
44
- // export const removeLeadingSlash = (str = '') => str.replace(/^\.?\//, '')
45
- // export const removeTrailingSearch = (str = '') => str.replace(/\?[\s\S]*$/, '')
46
- const addLeadingSlash = (url = '') => (url.charAt(0) === '/' ? url : '/' + url);
47
- const hasBasename = (path = '', prefix = '') => new RegExp('^' + prefix + '(\\/|\\?|#|$)', 'i').test(path) || path === prefix;
48
- const stripBasename = (path = '', prefix = '') => hasBasename(path, prefix) ? path.substring(prefix.length) : path;
49
- const stripTrailing = (str = '') => str.replace(/[?#][\s\S]*$/, '');
50
- const getHomePage = (path = '', basename = '', customRoutes = {}, entryPagePath = '') => {
51
- var _a;
52
- const routePath = addLeadingSlash(stripBasename(path, basename));
53
- const alias = ((_a = Object.entries(customRoutes).find(([key]) => key === routePath)) === null || _a === void 0 ? void 0 : _a[1]) || routePath;
54
- return entryPagePath || (typeof alias === 'string' ? alias : alias[0]) || basename;
55
- };
56
- const getCurrentPage = (routerMode = 'hash', basename = '/') => {
57
- const pagePath = routerMode === 'hash'
58
- ? location.hash.slice(1).split('?')[0]
59
- : location.pathname;
60
- return addLeadingSlash(stripBasename(pagePath, basename));
61
- };
62
- class RoutesAlias {
63
- constructor() {
64
- this.conf = [];
65
- this.getConfig = (url = '') => {
66
- const customRoute = this.conf.filter((arr) => {
67
- return arr.includes(url);
68
- });
69
- return customRoute[0];
70
- };
71
- this.getOrigin = (url = '') => {
72
- var _a;
73
- return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[0]) || url;
74
- };
75
- this.getAlias = (url = '') => {
76
- var _a;
77
- return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[1]) || url;
78
- };
79
- this.getAll = (url = '') => {
80
- return this.conf
81
- .filter((arr) => arr.includes(url))
82
- .reduceRight((p, a) => {
83
- p.unshift(a[1]);
84
- return p;
85
- }, []);
86
- };
87
- }
88
- set(customRoutes = {}) {
89
- for (let key in customRoutes) {
90
- const path = customRoutes[key];
91
- key = addLeadingSlash(key);
92
- if (typeof path === 'string') {
93
- this.conf.push([key, addLeadingSlash(path)]);
94
- }
95
- else if ((path === null || path === void 0 ? void 0 : path.length) > 0) {
96
- this.conf.push(...path.map(p => [key, addLeadingSlash(p)]));
97
- }
98
- }
99
- }
100
- }
101
- const routesAlias = new RoutesAlias();
102
-
103
44
  class RouterConfig {
104
45
  static set config(e) {
105
46
  this.__config = e;
@@ -118,7 +59,7 @@ class RouterConfig {
118
59
  }
119
60
  static get customRoutes() { return this.router.customRoutes || {}; }
120
61
  static isPage(url = '') {
121
- return this.pages.findIndex(e => addLeadingSlash(e) === url) !== -1;
62
+ return this.pages.findIndex(e => prependBasename(e) === url) !== -1;
122
63
  }
123
64
  }
124
65
 
@@ -157,7 +98,7 @@ class MpaHistory {
157
98
  return url;
158
99
  }
159
100
  push(to, _state = {}) {
160
- window.location.pathname = this.parseUrl(to);
101
+ window.location.assign(this.parseUrl(to));
161
102
  // this.pushState(_state, '', this.parseUrl(to))
162
103
  }
163
104
  replace(to, _state = {}) {
@@ -302,6 +243,65 @@ class Stacks {
302
243
  }
303
244
  const stacks = new Stacks();
304
245
 
246
+ // export const removeLeadingSlash = (str = '') => str.replace(/^\.?\//, '')
247
+ // export const removeTrailingSearch = (str = '') => str.replace(/\?[\s\S]*$/, '')
248
+ const addLeadingSlash = (url = '') => (url.charAt(0) === '/' ? url : '/' + url);
249
+ const hasBasename = (path = '', prefix = '') => new RegExp('^' + prefix + '(\\/|\\?|#|$)', 'i').test(path) || path === prefix;
250
+ const stripBasename = (path = '', prefix = '') => hasBasename(path, prefix) ? path.substring(prefix.length) : path;
251
+ const stripTrailing = (str = '') => str.replace(/[?#][\s\S]*$/, '');
252
+ const getHomePage = (path = '', basename = '', customRoutes = {}, entryPagePath = '') => {
253
+ var _a;
254
+ const routePath = addLeadingSlash(stripBasename(path, basename));
255
+ const alias = ((_a = Object.entries(customRoutes).find(([key]) => key === routePath)) === null || _a === void 0 ? void 0 : _a[1]) || routePath;
256
+ return entryPagePath || (typeof alias === 'string' ? alias : alias[0]) || basename;
257
+ };
258
+ const getCurrentPage = (routerMode = 'hash', basename = '/') => {
259
+ const pagePath = routerMode === 'hash'
260
+ ? location.hash.slice(1).split('?')[0]
261
+ : location.pathname;
262
+ return addLeadingSlash(stripBasename(pagePath, basename));
263
+ };
264
+ class RoutesAlias {
265
+ constructor() {
266
+ this.conf = [];
267
+ this.getConfig = (url = '') => {
268
+ const customRoute = this.conf.filter((arr) => {
269
+ return arr.includes(url);
270
+ });
271
+ return customRoute[0];
272
+ };
273
+ this.getOrigin = (url = '') => {
274
+ var _a;
275
+ return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[0]) || url;
276
+ };
277
+ this.getAlias = (url = '') => {
278
+ var _a;
279
+ return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[1]) || url;
280
+ };
281
+ this.getAll = (url = '') => {
282
+ return this.conf
283
+ .filter((arr) => arr.includes(url))
284
+ .reduceRight((p, a) => {
285
+ p.unshift(a[1]);
286
+ return p;
287
+ }, []);
288
+ };
289
+ }
290
+ set(customRoutes = {}) {
291
+ for (let key in customRoutes) {
292
+ const path = customRoutes[key];
293
+ key = addLeadingSlash(key);
294
+ if (typeof path === 'string') {
295
+ this.conf.push([key, addLeadingSlash(path)]);
296
+ }
297
+ else if ((path === null || path === void 0 ? void 0 : path.length) > 0) {
298
+ this.conf.push(...path.map(p => [key, addLeadingSlash(p)]));
299
+ }
300
+ }
301
+ }
302
+ }
303
+ const routesAlias = new RoutesAlias();
304
+
305
305
  function processNavigateUrl(option) {
306
306
  var _a;
307
307
  const pathPieces = history.parsePath(option.url);
@@ -355,7 +355,12 @@ function navigate(option, method) {
355
355
  }
356
356
  else if (method === 'navigateBack') {
357
357
  stacks.delta = option.delta;
358
- exports.history.go(-option.delta);
358
+ if (stacks.length > option.delta) {
359
+ exports.history.go(-option.delta);
360
+ }
361
+ else {
362
+ exports.history.go(1 - stacks.length);
363
+ }
359
364
  }
360
365
  }
361
366
  catch (error) {
@@ -440,11 +445,11 @@ function bindPageResize(page) {
440
445
 
441
446
  const pageScrollFn = {};
442
447
  let pageDOM = window;
443
- function bindPageScroll(page, pageEl, distance = 50) {
448
+ function bindPageScroll(page, scrollEl, distance = 50) {
444
449
  var _a;
445
450
  const pagePath = (page ? page === null || page === void 0 ? void 0 : page.path : (_a = runtime.Current.router) === null || _a === void 0 ? void 0 : _a.path);
446
- pageScrollFn[pagePath] && pageEl.removeEventListener('scroll', pageScrollFn[pagePath]);
447
- pageDOM = pageEl;
451
+ pageScrollFn[pagePath] && scrollEl.removeEventListener('scroll', pageScrollFn[pagePath]);
452
+ pageDOM = scrollEl;
448
453
  let isReachBottom = false;
449
454
  pageScrollFn[pagePath] = function () {
450
455
  var _a;
@@ -472,6 +477,75 @@ function getOffset() {
472
477
  }
473
478
  }
474
479
 
480
+ /**
481
+ * 插入页面动画需要的样式
482
+ */
483
+ function loadAnimateStyle(ms = 300) {
484
+ const css = `
485
+ .taro_router > .taro_page {
486
+ position: absolute;
487
+ left: 0;
488
+ top: 0;
489
+ width: 100%;
490
+ height: 100%;
491
+ background-color: #fff;
492
+ transform: translate(100%, 0);
493
+ transition: transform ${ms}ms;
494
+ z-index: 0;
495
+ }
496
+
497
+ .taro_router > .taro_page.taro_tabbar_page,
498
+ .taro_router > .taro_page.taro_page_show.taro_page_stationed {
499
+ transform: none;
500
+ }
501
+
502
+ .taro_router > .taro_page.taro_page_show {
503
+ transform: translate(0, 0);
504
+ }
505
+
506
+ .taro_page_shade,
507
+ .taro_router > .taro_page.taro_page_show.taro_page_stationed:not(.taro_page_shade):not(.taro_tabbar_page):not(:last-child) {
508
+ display: none;
509
+ }`;
510
+ addStyle(css);
511
+ }
512
+ /**
513
+ * 插入路由相关样式
514
+ */
515
+ function loadRouterStyle(usingWindowScroll) {
516
+ const css = `
517
+ .taro_router {
518
+ position: relative;
519
+ width: 100%;
520
+ height: 100%;
521
+ }
522
+
523
+ .taro_page {
524
+ width: 100%;
525
+ height: 100%;
526
+ ${usingWindowScroll ? '' : `
527
+ overflow-x: hidden;
528
+ overflow-y: scroll;
529
+ max-height: 100vh;
530
+ `}
531
+ }
532
+
533
+ .taro-tabbar__container .taro-tabbar__panel {
534
+ overflow: hidden;
535
+ max-height: calc(100vh - var(--taro-tabbar-height) - constant(safe-area-inset-bottom));
536
+ max-height: calc(100vh - var(--taro-tabbar-height) - env(safe-area-inset-bottom));
537
+ }
538
+ `;
539
+ addStyle(css);
540
+ }
541
+ function addStyle(css) {
542
+ if (!css)
543
+ return;
544
+ const style = document.createElement('style');
545
+ style.innerHTML = css;
546
+ document.getElementsByTagName('head')[0].appendChild(style);
547
+ }
548
+
475
549
  // @ts-nocheck
476
550
  function initTabbar(config) {
477
551
  if (config.tabBar == null) {
@@ -532,6 +606,17 @@ class MultiPageHandler {
532
606
  return !!pagePath && this.tabBarList.some(t => t.pagePath === pagePath);
533
607
  }
534
608
  get search() { return location.search.substr(1); }
609
+ get usingWindowScroll() {
610
+ var _a;
611
+ let usingWindowScroll = true;
612
+ if (typeof ((_a = this.pageConfig) === null || _a === void 0 ? void 0 : _a.usingWindowScroll) === 'boolean') {
613
+ usingWindowScroll = this.pageConfig.usingWindowScroll;
614
+ }
615
+ const win = window;
616
+ win.__taroAppConfig || (win.__taroAppConfig = {});
617
+ win.__taroAppConfig.usingWindowScroll = usingWindowScroll;
618
+ return usingWindowScroll;
619
+ }
535
620
  getQuery(search = '', options = {}) {
536
621
  search = search ? `${search}&${this.search}` : this.search;
537
622
  const query = search
@@ -541,6 +626,7 @@ class MultiPageHandler {
541
626
  }
542
627
  mount() {
543
628
  setHistoryMode(this.routerMode, this.router.basename);
629
+ loadRouterStyle(this.usingWindowScroll);
544
630
  const appId = this.appId;
545
631
  let app = document.getElementById(appId);
546
632
  let isPosition = true;
@@ -577,7 +663,20 @@ class MultiPageHandler {
577
663
  const pageEl = this.getPageContainer(page);
578
664
  if (pageEl && !(pageEl === null || pageEl === void 0 ? void 0 : pageEl['__isReady'])) {
579
665
  const el = pageEl.firstElementChild;
580
- (_a = el === null || el === void 0 ? void 0 : el['componentOnReady']) === null || _a === void 0 ? void 0 : _a.call(el);
666
+ const componentOnReady = el === null || el === void 0 ? void 0 : el['componentOnReady'];
667
+ if (componentOnReady) {
668
+ componentOnReady === null || componentOnReady === void 0 ? void 0 : componentOnReady().then(() => {
669
+ requestAnimationFrame(() => {
670
+ var _a;
671
+ (_a = page.onReady) === null || _a === void 0 ? void 0 : _a.call(page);
672
+ pageEl['__isReady'] = true;
673
+ });
674
+ });
675
+ }
676
+ else {
677
+ (_a = page.onReady) === null || _a === void 0 ? void 0 : _a.call(page);
678
+ pageEl['__isReady'] = true;
679
+ }
581
680
  onLoad && (pageEl['__page'] = page);
582
681
  }
583
682
  }
@@ -587,11 +686,14 @@ class MultiPageHandler {
587
686
  return;
588
687
  (_a = page.onLoad) === null || _a === void 0 ? void 0 : _a.call(page, this.getQuery('', page.options), () => {
589
688
  var _a;
590
- const pageEl = this.getPageContainer(page);
591
- this.isTabBar && (pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.add('taro_tabbar_page'));
689
+ if (this.isTabBar) {
690
+ const pageEl = this.getPageContainer(page);
691
+ pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.add('taro_tabbar_page');
692
+ }
592
693
  this.onReady(page, true);
593
694
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
594
- this.bindPageEvents(page, pageEl, pageConfig);
695
+ this.bindPageEvents(page, pageConfig);
696
+ this.triggerRouterChange();
595
697
  });
596
698
  }
597
699
  getPageContainer(page) {
@@ -605,17 +707,33 @@ class MultiPageHandler {
605
707
  ? document.querySelector(`.taro_page#${id}`)
606
708
  : document.querySelector('.taro_page') ||
607
709
  document.querySelector('.taro_router'));
608
- return el || window;
710
+ return el;
711
+ }
712
+ getScrollingElement(page) {
713
+ if (this.usingWindowScroll)
714
+ return window;
715
+ return this.getPageContainer(page) || window;
609
716
  }
610
- bindPageEvents(page, pageEl, config = {}) {
717
+ bindPageEvents(page, config = {}) {
611
718
  var _a;
612
- if (!pageEl) {
613
- pageEl = this.getPageContainer();
614
- }
719
+ const scrollEl = this.getScrollingElement(page);
615
720
  const distance = config.onReachBottomDistance || ((_a = this.config.window) === null || _a === void 0 ? void 0 : _a.onReachBottomDistance) || 50;
616
- bindPageScroll(page, pageEl, distance);
721
+ bindPageScroll(page, scrollEl, distance);
617
722
  bindPageResize(page);
618
723
  }
724
+ triggerRouterChange() {
725
+ /**
726
+ * @tarojs/runtime 中生命周期跑在 promise 中,所以这里需要 setTimeout 延迟事件调用
727
+ * TODO 考虑将生命周期返回 Promise,用于处理相关事件调用顺序
728
+ */
729
+ setTimeout(() => {
730
+ runtime.eventCenter.trigger('__afterTaroRouterChange', {
731
+ toLocation: {
732
+ path: this.pathname
733
+ }
734
+ });
735
+ }, 0);
736
+ }
619
737
  }
620
738
 
621
739
  const createStampId$1 = runtime.incrementId();
@@ -631,6 +749,9 @@ const launchStampId$1 = createStampId$1();
631
749
  function createMultiRouter(app, config, framework) {
632
750
  var _a, _b, _c, _d, _e, _f;
633
751
  return __awaiter(this, void 0, void 0, function* () {
752
+ if (typeof app.onUnhandledRejection === 'function') {
753
+ window.addEventListener('unhandledrejection', app.onUnhandledRejection);
754
+ }
634
755
  RouterConfig.config = config;
635
756
  const handler = new MultiPageHandler(config);
636
757
  const launchParam = {
@@ -673,48 +794,13 @@ function createMultiRouter(app, config, framework) {
673
794
  const loadConfig = Object.assign({}, pageConfig);
674
795
  delete loadConfig['path'];
675
796
  delete loadConfig['load'];
676
- const page = runtime.createPageConfig(enablePullDownRefresh ? runtime.hooks.call('createPullDownComponent', el, location.pathname, framework, handler.PullDownRefresh) : el, pathName + runtime.stringify(launchParam), {}, loadConfig);
797
+ const page = runtime.createPageConfig(enablePullDownRefresh ? runtime.hooks.call('createPullDownComponent', el, pathName, framework, handler.PullDownRefresh) : el, pathName + runtime.stringify(launchParam), {}, loadConfig);
677
798
  handler.load(page, pageConfig);
678
799
  (_f = app.onShow) === null || _f === void 0 ? void 0 : _f.call(app, launchParam);
679
800
  });
680
801
  }
681
802
 
682
- /**
683
- * 插入页面动画需要的样式
684
- */
685
- function loadAnimateStyle(ms = 300) {
686
- const css = `
687
- .taro_router .taro_page {
688
- position: absolute;
689
- left: 0;
690
- top: 0;
691
- width: 100%;
692
- height: 100%;
693
- background-color: #fff;
694
- transform: translate(100%, 0);
695
- transition: transform ${ms}ms;
696
- z-index: 0;
697
- }
698
-
699
- .taro_router .taro_page.taro_tabbar_page,
700
- .taro_router .taro_page.taro_page_show.taro_page_stationed {
701
- transform: none;
702
- }
703
-
704
- .taro_router .taro_page.taro_page_show {
705
- transform: translate(0, 0);
706
- }`;
707
- const style = document.createElement('style');
708
- style.innerHTML = css;
709
- document.getElementsByTagName('head')[0].appendChild(style);
710
- }
711
-
712
803
  /* eslint-disable dot-notation */
713
- function setDisplay(el, type = '') {
714
- if (el) {
715
- el.style.display = type;
716
- }
717
- }
718
804
  class PageHandler {
719
805
  constructor(config) {
720
806
  this.defaultAnimation = { duration: 300, delay: 50 };
@@ -794,6 +880,17 @@ class PageHandler {
794
880
  }
795
881
  return search.substring(1);
796
882
  }
883
+ get usingWindowScroll() {
884
+ var _a;
885
+ let usingWindowScroll = false;
886
+ if (typeof ((_a = this.pageConfig) === null || _a === void 0 ? void 0 : _a.usingWindowScroll) === 'boolean') {
887
+ usingWindowScroll = this.pageConfig.usingWindowScroll;
888
+ }
889
+ const win = window;
890
+ win.__taroAppConfig || (win.__taroAppConfig = {});
891
+ win.__taroAppConfig.usingWindowScroll = usingWindowScroll;
892
+ return usingWindowScroll;
893
+ }
797
894
  getQuery(stamp = '', search = '', options = {}) {
798
895
  search = search ? `${search}&${this.search}` : this.search;
799
896
  const query = search
@@ -804,7 +901,9 @@ class PageHandler {
804
901
  }
805
902
  mount() {
806
903
  setHistoryMode(this.routerMode, this.router.basename);
904
+ this.pathname = exports.history.location.pathname;
807
905
  this.animation && loadAnimateStyle(this.animationDuration);
906
+ loadRouterStyle(this.usingWindowScroll);
808
907
  const appId = this.appId;
809
908
  let app = document.getElementById(appId);
810
909
  let isPosition = true;
@@ -867,11 +966,12 @@ class PageHandler {
867
966
  const param = this.getQuery(stampId, '', page.options);
868
967
  let pageEl = this.getPageContainer(page);
869
968
  if (pageEl) {
870
- setDisplay(pageEl);
969
+ pageEl.classList.remove('taro_page_shade');
871
970
  this.isTabBar(this.pathname) && pageEl.classList.add('taro_tabbar_page');
872
971
  this.addAnimation(pageEl, pageNo === 0);
873
972
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
874
- this.bindPageEvents(page, pageEl, pageConfig);
973
+ this.bindPageEvents(page, pageConfig);
974
+ this.triggerRouterChange();
875
975
  }
876
976
  else {
877
977
  (_b = page.onLoad) === null || _b === void 0 ? void 0 : _b.call(page, param, () => {
@@ -881,7 +981,8 @@ class PageHandler {
881
981
  this.addAnimation(pageEl, pageNo === 0);
882
982
  this.onReady(page, true);
883
983
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
884
- this.bindPageEvents(page, pageEl, pageConfig);
984
+ this.bindPageEvents(page, pageConfig);
985
+ this.triggerRouterChange();
885
986
  });
886
987
  }
887
988
  }
@@ -901,10 +1002,14 @@ class PageHandler {
901
1002
  const pageEl = this.getPageContainer(page);
902
1003
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_stationed');
903
1004
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_show');
1005
+ if (pageEl) {
1006
+ pageEl.style.zIndex = '1';
1007
+ }
904
1008
  this.unloadTimer = setTimeout(() => {
905
1009
  var _a, _b;
906
1010
  this.unloadTimer = null;
907
1011
  (_b = (_a = this.lastUnloadPage) === null || _a === void 0 ? void 0 : _a.onUnload) === null || _b === void 0 ? void 0 : _b.call(_a);
1012
+ runtime.eventCenter.trigger('__taroPageOnShowAfterDestroyed');
908
1013
  }, this.animationDuration);
909
1014
  }
910
1015
  else {
@@ -912,6 +1017,9 @@ class PageHandler {
912
1017
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_stationed');
913
1018
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_show');
914
1019
  (_c = page === null || page === void 0 ? void 0 : page.onUnload) === null || _c === void 0 ? void 0 : _c.call(page);
1020
+ setTimeout(() => {
1021
+ runtime.eventCenter.trigger('__taroPageOnShowAfterDestroyed');
1022
+ }, 0);
915
1023
  }
916
1024
  if (delta >= 1)
917
1025
  this.unload(stacks.last, delta);
@@ -923,10 +1031,11 @@ class PageHandler {
923
1031
  const param = this.getQuery(page['$taroParams']['stamp'], '', page.options);
924
1032
  let pageEl = this.getPageContainer(page);
925
1033
  if (pageEl) {
926
- setDisplay(pageEl);
1034
+ pageEl.classList.remove('taro_page_shade');
927
1035
  this.addAnimation(pageEl, pageNo === 0);
928
1036
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
929
- this.bindPageEvents(page, pageEl, pageConfig);
1037
+ this.bindPageEvents(page, pageConfig);
1038
+ this.triggerRouterChange();
930
1039
  }
931
1040
  else {
932
1041
  (_b = page.onLoad) === null || _b === void 0 ? void 0 : _b.call(page, param, () => {
@@ -935,7 +1044,8 @@ class PageHandler {
935
1044
  this.addAnimation(pageEl, pageNo === 0);
936
1045
  this.onReady(page, false);
937
1046
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
938
- this.bindPageEvents(page, pageEl, pageConfig);
1047
+ this.bindPageEvents(page, pageConfig);
1048
+ this.triggerRouterChange();
939
1049
  });
940
1050
  }
941
1051
  }
@@ -949,12 +1059,12 @@ class PageHandler {
949
1059
  if (this.hideTimer) {
950
1060
  clearTimeout(this.hideTimer);
951
1061
  this.hideTimer = null;
952
- setDisplay(this.lastHidePage, 'none');
1062
+ pageEl.classList.add('taro_page_shade');
953
1063
  }
954
1064
  this.lastHidePage = pageEl;
955
1065
  this.hideTimer = setTimeout(() => {
956
1066
  this.hideTimer = null;
957
- setDisplay(this.lastHidePage, 'none');
1067
+ pageEl.classList.add('taro_page_shade');
958
1068
  }, this.animationDuration + this.animationDelay);
959
1069
  (_a = page.onHide) === null || _a === void 0 ? void 0 : _a.call(page);
960
1070
  }
@@ -989,23 +1099,42 @@ class PageHandler {
989
1099
  ? document.querySelector(`.taro_page#${id}`)
990
1100
  : document.querySelector('.taro_page') ||
991
1101
  document.querySelector('.taro_router'));
992
- return el || window;
1102
+ return el;
993
1103
  }
994
- bindPageEvents(page, pageEl, config = {}) {
1104
+ getScrollingElement(page) {
1105
+ if (this.usingWindowScroll)
1106
+ return window;
1107
+ return this.getPageContainer(page) || window;
1108
+ }
1109
+ bindPageEvents(page, config = {}) {
995
1110
  var _a;
996
- if (!pageEl) {
997
- pageEl = this.getPageContainer();
998
- }
1111
+ const scrollEl = this.getScrollingElement(page);
999
1112
  const distance = config.onReachBottomDistance || ((_a = this.config.window) === null || _a === void 0 ? void 0 : _a.onReachBottomDistance) || 50;
1000
- bindPageScroll(page, pageEl, distance);
1113
+ bindPageScroll(page, scrollEl, distance);
1001
1114
  bindPageResize(page);
1002
1115
  }
1116
+ triggerRouterChange() {
1117
+ /**
1118
+ * @tarojs/runtime 中生命周期跑在 promise 中,所以这里需要 setTimeout 延迟事件调用
1119
+ * TODO 考虑将生命周期返回 Promise,用于处理相关事件调用顺序
1120
+ */
1121
+ setTimeout(() => {
1122
+ runtime.eventCenter.trigger('__afterTaroRouterChange', {
1123
+ toLocation: {
1124
+ path: this.pathname
1125
+ }
1126
+ });
1127
+ }, 0);
1128
+ }
1003
1129
  }
1004
1130
 
1005
1131
  const createStampId = runtime.incrementId();
1006
1132
  let launchStampId = createStampId();
1007
1133
  function createRouter(app, config, framework) {
1008
1134
  var _a, _b;
1135
+ if (typeof app.onUnhandledRejection === 'function') {
1136
+ window.addEventListener('unhandledrejection', app.onUnhandledRejection);
1137
+ }
1009
1138
  RouterConfig.config = config;
1010
1139
  const handler = new PageHandler(config);
1011
1140
  routesAlias.set(handler.router.customRoutes);
@@ -1030,8 +1159,10 @@ function createRouter(app, config, framework) {
1030
1159
  (_a = app.onLaunch) === null || _a === void 0 ? void 0 : _a.call(app, launchParam);
1031
1160
  app.onError && window.addEventListener('error', e => { var _a; return (_a = app.onError) === null || _a === void 0 ? void 0 : _a.call(app, e.message); });
1032
1161
  const render = ({ location, action }) => __awaiter(this, void 0, void 0, function* () {
1033
- var _c, _d, _e, _f, _g;
1162
+ var _c, _d, _e, _f, _g, _h;
1034
1163
  handler.pathname = decodeURI(location.pathname);
1164
+ if ((_c = window.__taroAppConfig) === null || _c === void 0 ? void 0 : _c.usingWindowScroll)
1165
+ window.scrollTo(0, 0);
1035
1166
  runtime.eventCenter.trigger('__taroRouterChange', {
1036
1167
  toLocation: {
1037
1168
  path: handler.pathname
@@ -1044,9 +1175,13 @@ function createRouter(app, config, framework) {
1044
1175
  }
1045
1176
  catch (error) {
1046
1177
  if (error.status === 404) {
1047
- (_c = app.onPageNotFound) === null || _c === void 0 ? void 0 : _c.call(app, {
1048
- path: handler.pathname
1049
- });
1178
+ const notFoundEvent = {
1179
+ isEntryPage: stacks.length === 0,
1180
+ path: handler.pathname,
1181
+ query: handler.getQuery(createStampId()),
1182
+ };
1183
+ (_d = app.onPageNotFound) === null || _d === void 0 ? void 0 : _d.call(app, notFoundEvent);
1184
+ runtime.eventCenter.trigger('__taroRouterNotFound', notFoundEvent);
1050
1185
  }
1051
1186
  else if (/Loading hot update .* failed./.test(error.message)) {
1052
1187
  // NOTE: webpack5 与 prebundle 搭配使用时,开发环境下初次启动时偶发错误,由于 HMR 加载 chunk hash 错误,导致热更新失败
@@ -1059,16 +1194,16 @@ function createRouter(app, config, framework) {
1059
1194
  if (!element)
1060
1195
  return;
1061
1196
  const pageConfig = handler.pageConfig;
1062
- let enablePullDownRefresh = ((_d = config === null || config === void 0 ? void 0 : config.window) === null || _d === void 0 ? void 0 : _d.enablePullDownRefresh) || false;
1197
+ let enablePullDownRefresh = ((_e = config === null || config === void 0 ? void 0 : config.window) === null || _e === void 0 ? void 0 : _e.enablePullDownRefresh) || false;
1063
1198
  if (pageConfig) {
1064
- setTitle((_e = pageConfig.navigationBarTitleText) !== null && _e !== void 0 ? _e : document.title);
1199
+ setTitle((_f = pageConfig.navigationBarTitleText) !== null && _f !== void 0 ? _f : document.title);
1065
1200
  if (typeof pageConfig.enablePullDownRefresh === 'boolean') {
1066
1201
  enablePullDownRefresh = pageConfig.enablePullDownRefresh;
1067
1202
  }
1068
1203
  }
1069
1204
  const currentPage = runtime.Current.page;
1070
1205
  const pathname = handler.pathname;
1071
- const methodName = (_f = stacks.method) !== null && _f !== void 0 ? _f : '';
1206
+ const methodName = (_g = stacks.method) !== null && _g !== void 0 ? _g : '';
1072
1207
  const cacheTabs = stacks.getTabs();
1073
1208
  let shouldLoad = false;
1074
1209
  stacks.method = '';
@@ -1093,11 +1228,11 @@ function createRouter(app, config, framework) {
1093
1228
  else if (stacks.length > 0) {
1094
1229
  const firstIns = stacks.getItem(0);
1095
1230
  if (handler.isTabBar(firstIns.path)) {
1096
- handler.unload(currentPage, stacks.length - 1);
1231
+ handler.unload(currentPage, stacks.length - 1, true);
1097
1232
  stacks.pushTab(firstIns.path.split('?')[0]);
1098
1233
  }
1099
1234
  else {
1100
- handler.unload(currentPage, stacks.length);
1235
+ handler.unload(currentPage, stacks.length, true);
1101
1236
  }
1102
1237
  }
1103
1238
  if (cacheTabs[handler.pathname]) {
@@ -1114,7 +1249,9 @@ function createRouter(app, config, framework) {
1114
1249
  if (currentPage !== stacks.getItem(prevIndex)) {
1115
1250
  handler.unload(currentPage, delta, prevIndex > -1);
1116
1251
  if (prevIndex > -1) {
1117
- handler.show(stacks.getItem(prevIndex), pageConfig, prevIndex);
1252
+ runtime.eventCenter.once('__taroPageOnShowAfterDestroyed', () => {
1253
+ handler.show(stacks.getItem(prevIndex), pageConfig, prevIndex);
1254
+ });
1118
1255
  }
1119
1256
  else {
1120
1257
  shouldLoad = true;
@@ -1132,7 +1269,7 @@ function createRouter(app, config, framework) {
1132
1269
  shouldLoad = true;
1133
1270
  }
1134
1271
  if (shouldLoad || stacks.length < 1) {
1135
- const el = (_g = element.default) !== null && _g !== void 0 ? _g : element;
1272
+ const el = (_h = element.default) !== null && _h !== void 0 ? _h : element;
1136
1273
  const loadConfig = Object.assign({}, pageConfig);
1137
1274
  const stacksIndex = stacks.length;
1138
1275
  delete loadConfig['path'];
@@ -1145,16 +1282,11 @@ function createRouter(app, config, framework) {
1145
1282
  else {
1146
1283
  pageStampId = createStampId();
1147
1284
  }
1148
- const page = runtime.createPageConfig(enablePullDownRefresh ? runtime.hooks.call('createPullDownComponent', el, location.pathname, framework, handler.PullDownRefresh) : el, pathname + runtime.stringify(handler.getQuery(pageStampId)), {}, loadConfig);
1285
+ const page = runtime.createPageConfig(enablePullDownRefresh ? runtime.hooks.call('createPullDownComponent', el, pathname, framework, handler.PullDownRefresh, pageStampId) : el, pathname + runtime.stringify(handler.getQuery(pageStampId)), {}, loadConfig);
1149
1286
  if (params)
1150
1287
  page.options = params;
1151
1288
  handler.load(page, pageConfig, pageStampId, stacksIndex);
1152
1289
  }
1153
- runtime.eventCenter.trigger('__afterTaroRouterChange', {
1154
- toLocation: {
1155
- path: handler.pathname
1156
- }
1157
- });
1158
1290
  });
1159
1291
  const routePath = addLeadingSlash(stripBasename(exports.history.location.pathname, handler.basename));
1160
1292
  if (routePath === '/') {