@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.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,78 @@ 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
+ }
536
+
537
+ .taro-tabbar__container > .taro-tabbar__panel > .taro_page.taro_tabbar_page {
538
+ max-height: calc(100vh - var(--taro-tabbar-height) - constant(safe-area-inset-bottom));
539
+ max-height: calc(100vh - var(--taro-tabbar-height) - env(safe-area-inset-bottom));
540
+ }
541
+ `;
542
+ addStyle(css);
543
+ }
544
+ function addStyle(css) {
545
+ if (!css)
546
+ return;
547
+ const style = document.createElement('style');
548
+ style.innerHTML = css;
549
+ document.getElementsByTagName('head')[0].appendChild(style);
550
+ }
551
+
475
552
  // @ts-nocheck
476
553
  function initTabbar(config) {
477
554
  if (config.tabBar == null) {
@@ -532,6 +609,17 @@ class MultiPageHandler {
532
609
  return !!pagePath && this.tabBarList.some(t => t.pagePath === pagePath);
533
610
  }
534
611
  get search() { return location.search.substr(1); }
612
+ get usingWindowScroll() {
613
+ var _a;
614
+ let usingWindowScroll = true;
615
+ if (typeof ((_a = this.pageConfig) === null || _a === void 0 ? void 0 : _a.usingWindowScroll) === 'boolean') {
616
+ usingWindowScroll = this.pageConfig.usingWindowScroll;
617
+ }
618
+ const win = window;
619
+ win.__taroAppConfig || (win.__taroAppConfig = {});
620
+ win.__taroAppConfig.usingWindowScroll = usingWindowScroll;
621
+ return usingWindowScroll;
622
+ }
535
623
  getQuery(search = '', options = {}) {
536
624
  search = search ? `${search}&${this.search}` : this.search;
537
625
  const query = search
@@ -541,6 +629,7 @@ class MultiPageHandler {
541
629
  }
542
630
  mount() {
543
631
  setHistoryMode(this.routerMode, this.router.basename);
632
+ loadRouterStyle(this.usingWindowScroll);
544
633
  const appId = this.appId;
545
634
  let app = document.getElementById(appId);
546
635
  let isPosition = true;
@@ -577,7 +666,20 @@ class MultiPageHandler {
577
666
  const pageEl = this.getPageContainer(page);
578
667
  if (pageEl && !(pageEl === null || pageEl === void 0 ? void 0 : pageEl['__isReady'])) {
579
668
  const el = pageEl.firstElementChild;
580
- (_a = el === null || el === void 0 ? void 0 : el['componentOnReady']) === null || _a === void 0 ? void 0 : _a.call(el);
669
+ const componentOnReady = el === null || el === void 0 ? void 0 : el['componentOnReady'];
670
+ if (componentOnReady) {
671
+ componentOnReady === null || componentOnReady === void 0 ? void 0 : componentOnReady().then(() => {
672
+ requestAnimationFrame(() => {
673
+ var _a;
674
+ (_a = page.onReady) === null || _a === void 0 ? void 0 : _a.call(page);
675
+ pageEl['__isReady'] = true;
676
+ });
677
+ });
678
+ }
679
+ else {
680
+ (_a = page.onReady) === null || _a === void 0 ? void 0 : _a.call(page);
681
+ pageEl['__isReady'] = true;
682
+ }
581
683
  onLoad && (pageEl['__page'] = page);
582
684
  }
583
685
  }
@@ -587,11 +689,14 @@ class MultiPageHandler {
587
689
  return;
588
690
  (_a = page.onLoad) === null || _a === void 0 ? void 0 : _a.call(page, this.getQuery('', page.options), () => {
589
691
  var _a;
590
- const pageEl = this.getPageContainer(page);
591
- this.isTabBar && (pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.add('taro_tabbar_page'));
692
+ if (this.isTabBar) {
693
+ const pageEl = this.getPageContainer(page);
694
+ pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.add('taro_tabbar_page');
695
+ }
592
696
  this.onReady(page, true);
593
697
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
594
- this.bindPageEvents(page, pageEl, pageConfig);
698
+ this.bindPageEvents(page, pageConfig);
699
+ this.triggerRouterChange();
595
700
  });
596
701
  }
597
702
  getPageContainer(page) {
@@ -605,17 +710,33 @@ class MultiPageHandler {
605
710
  ? document.querySelector(`.taro_page#${id}`)
606
711
  : document.querySelector('.taro_page') ||
607
712
  document.querySelector('.taro_router'));
608
- return el || window;
713
+ return el;
714
+ }
715
+ getScrollingElement(page) {
716
+ if (this.usingWindowScroll)
717
+ return window;
718
+ return this.getPageContainer(page) || window;
609
719
  }
610
- bindPageEvents(page, pageEl, config = {}) {
720
+ bindPageEvents(page, config = {}) {
611
721
  var _a;
612
- if (!pageEl) {
613
- pageEl = this.getPageContainer();
614
- }
722
+ const scrollEl = this.getScrollingElement(page);
615
723
  const distance = config.onReachBottomDistance || ((_a = this.config.window) === null || _a === void 0 ? void 0 : _a.onReachBottomDistance) || 50;
616
- bindPageScroll(page, pageEl, distance);
724
+ bindPageScroll(page, scrollEl, distance);
617
725
  bindPageResize(page);
618
726
  }
727
+ triggerRouterChange() {
728
+ /**
729
+ * @tarojs/runtime 中生命周期跑在 promise 中,所以这里需要 setTimeout 延迟事件调用
730
+ * TODO 考虑将生命周期返回 Promise,用于处理相关事件调用顺序
731
+ */
732
+ setTimeout(() => {
733
+ runtime.eventCenter.trigger('__afterTaroRouterChange', {
734
+ toLocation: {
735
+ path: this.pathname
736
+ }
737
+ });
738
+ }, 0);
739
+ }
619
740
  }
620
741
 
621
742
  const createStampId$1 = runtime.incrementId();
@@ -631,6 +752,9 @@ const launchStampId$1 = createStampId$1();
631
752
  function createMultiRouter(app, config, framework) {
632
753
  var _a, _b, _c, _d, _e, _f;
633
754
  return __awaiter(this, void 0, void 0, function* () {
755
+ if (typeof app.onUnhandledRejection === 'function') {
756
+ window.addEventListener('unhandledrejection', app.onUnhandledRejection);
757
+ }
634
758
  RouterConfig.config = config;
635
759
  const handler = new MultiPageHandler(config);
636
760
  const launchParam = {
@@ -673,48 +797,13 @@ function createMultiRouter(app, config, framework) {
673
797
  const loadConfig = Object.assign({}, pageConfig);
674
798
  delete loadConfig['path'];
675
799
  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);
800
+ const page = runtime.createPageConfig(enablePullDownRefresh ? runtime.hooks.call('createPullDownComponent', el, pathName, framework, handler.PullDownRefresh) : el, pathName + runtime.stringify(launchParam), {}, loadConfig);
677
801
  handler.load(page, pageConfig);
678
802
  (_f = app.onShow) === null || _f === void 0 ? void 0 : _f.call(app, launchParam);
679
803
  });
680
804
  }
681
805
 
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
806
  /* eslint-disable dot-notation */
713
- function setDisplay(el, type = '') {
714
- if (el) {
715
- el.style.display = type;
716
- }
717
- }
718
807
  class PageHandler {
719
808
  constructor(config) {
720
809
  this.defaultAnimation = { duration: 300, delay: 50 };
@@ -794,6 +883,17 @@ class PageHandler {
794
883
  }
795
884
  return search.substring(1);
796
885
  }
886
+ get usingWindowScroll() {
887
+ var _a;
888
+ let usingWindowScroll = false;
889
+ if (typeof ((_a = this.pageConfig) === null || _a === void 0 ? void 0 : _a.usingWindowScroll) === 'boolean') {
890
+ usingWindowScroll = this.pageConfig.usingWindowScroll;
891
+ }
892
+ const win = window;
893
+ win.__taroAppConfig || (win.__taroAppConfig = {});
894
+ win.__taroAppConfig.usingWindowScroll = usingWindowScroll;
895
+ return usingWindowScroll;
896
+ }
797
897
  getQuery(stamp = '', search = '', options = {}) {
798
898
  search = search ? `${search}&${this.search}` : this.search;
799
899
  const query = search
@@ -804,7 +904,9 @@ class PageHandler {
804
904
  }
805
905
  mount() {
806
906
  setHistoryMode(this.routerMode, this.router.basename);
907
+ this.pathname = exports.history.location.pathname;
807
908
  this.animation && loadAnimateStyle(this.animationDuration);
909
+ loadRouterStyle(this.usingWindowScroll);
808
910
  const appId = this.appId;
809
911
  let app = document.getElementById(appId);
810
912
  let isPosition = true;
@@ -867,11 +969,12 @@ class PageHandler {
867
969
  const param = this.getQuery(stampId, '', page.options);
868
970
  let pageEl = this.getPageContainer(page);
869
971
  if (pageEl) {
870
- setDisplay(pageEl);
972
+ pageEl.classList.remove('taro_page_shade');
871
973
  this.isTabBar(this.pathname) && pageEl.classList.add('taro_tabbar_page');
872
974
  this.addAnimation(pageEl, pageNo === 0);
873
975
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
874
- this.bindPageEvents(page, pageEl, pageConfig);
976
+ this.bindPageEvents(page, pageConfig);
977
+ this.triggerRouterChange();
875
978
  }
876
979
  else {
877
980
  (_b = page.onLoad) === null || _b === void 0 ? void 0 : _b.call(page, param, () => {
@@ -881,7 +984,8 @@ class PageHandler {
881
984
  this.addAnimation(pageEl, pageNo === 0);
882
985
  this.onReady(page, true);
883
986
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
884
- this.bindPageEvents(page, pageEl, pageConfig);
987
+ this.bindPageEvents(page, pageConfig);
988
+ this.triggerRouterChange();
885
989
  });
886
990
  }
887
991
  }
@@ -901,10 +1005,14 @@ class PageHandler {
901
1005
  const pageEl = this.getPageContainer(page);
902
1006
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_stationed');
903
1007
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_show');
1008
+ if (pageEl) {
1009
+ pageEl.style.zIndex = '1';
1010
+ }
904
1011
  this.unloadTimer = setTimeout(() => {
905
1012
  var _a, _b;
906
1013
  this.unloadTimer = null;
907
1014
  (_b = (_a = this.lastUnloadPage) === null || _a === void 0 ? void 0 : _a.onUnload) === null || _b === void 0 ? void 0 : _b.call(_a);
1015
+ runtime.eventCenter.trigger('__taroPageOnShowAfterDestroyed');
908
1016
  }, this.animationDuration);
909
1017
  }
910
1018
  else {
@@ -912,6 +1020,9 @@ class PageHandler {
912
1020
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_stationed');
913
1021
  pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_show');
914
1022
  (_c = page === null || page === void 0 ? void 0 : page.onUnload) === null || _c === void 0 ? void 0 : _c.call(page);
1023
+ setTimeout(() => {
1024
+ runtime.eventCenter.trigger('__taroPageOnShowAfterDestroyed');
1025
+ }, 0);
915
1026
  }
916
1027
  if (delta >= 1)
917
1028
  this.unload(stacks.last, delta);
@@ -923,10 +1034,11 @@ class PageHandler {
923
1034
  const param = this.getQuery(page['$taroParams']['stamp'], '', page.options);
924
1035
  let pageEl = this.getPageContainer(page);
925
1036
  if (pageEl) {
926
- setDisplay(pageEl);
1037
+ pageEl.classList.remove('taro_page_shade');
927
1038
  this.addAnimation(pageEl, pageNo === 0);
928
1039
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
929
- this.bindPageEvents(page, pageEl, pageConfig);
1040
+ this.bindPageEvents(page, pageConfig);
1041
+ this.triggerRouterChange();
930
1042
  }
931
1043
  else {
932
1044
  (_b = page.onLoad) === null || _b === void 0 ? void 0 : _b.call(page, param, () => {
@@ -935,7 +1047,8 @@ class PageHandler {
935
1047
  this.addAnimation(pageEl, pageNo === 0);
936
1048
  this.onReady(page, false);
937
1049
  (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
938
- this.bindPageEvents(page, pageEl, pageConfig);
1050
+ this.bindPageEvents(page, pageConfig);
1051
+ this.triggerRouterChange();
939
1052
  });
940
1053
  }
941
1054
  }
@@ -949,12 +1062,12 @@ class PageHandler {
949
1062
  if (this.hideTimer) {
950
1063
  clearTimeout(this.hideTimer);
951
1064
  this.hideTimer = null;
952
- setDisplay(this.lastHidePage, 'none');
1065
+ pageEl.classList.add('taro_page_shade');
953
1066
  }
954
1067
  this.lastHidePage = pageEl;
955
1068
  this.hideTimer = setTimeout(() => {
956
1069
  this.hideTimer = null;
957
- setDisplay(this.lastHidePage, 'none');
1070
+ pageEl.classList.add('taro_page_shade');
958
1071
  }, this.animationDuration + this.animationDelay);
959
1072
  (_a = page.onHide) === null || _a === void 0 ? void 0 : _a.call(page);
960
1073
  }
@@ -989,23 +1102,42 @@ class PageHandler {
989
1102
  ? document.querySelector(`.taro_page#${id}`)
990
1103
  : document.querySelector('.taro_page') ||
991
1104
  document.querySelector('.taro_router'));
992
- return el || window;
1105
+ return el;
993
1106
  }
994
- bindPageEvents(page, pageEl, config = {}) {
1107
+ getScrollingElement(page) {
1108
+ if (this.usingWindowScroll)
1109
+ return window;
1110
+ return this.getPageContainer(page) || window;
1111
+ }
1112
+ bindPageEvents(page, config = {}) {
995
1113
  var _a;
996
- if (!pageEl) {
997
- pageEl = this.getPageContainer();
998
- }
1114
+ const scrollEl = this.getScrollingElement(page);
999
1115
  const distance = config.onReachBottomDistance || ((_a = this.config.window) === null || _a === void 0 ? void 0 : _a.onReachBottomDistance) || 50;
1000
- bindPageScroll(page, pageEl, distance);
1116
+ bindPageScroll(page, scrollEl, distance);
1001
1117
  bindPageResize(page);
1002
1118
  }
1119
+ triggerRouterChange() {
1120
+ /**
1121
+ * @tarojs/runtime 中生命周期跑在 promise 中,所以这里需要 setTimeout 延迟事件调用
1122
+ * TODO 考虑将生命周期返回 Promise,用于处理相关事件调用顺序
1123
+ */
1124
+ setTimeout(() => {
1125
+ runtime.eventCenter.trigger('__afterTaroRouterChange', {
1126
+ toLocation: {
1127
+ path: this.pathname
1128
+ }
1129
+ });
1130
+ }, 0);
1131
+ }
1003
1132
  }
1004
1133
 
1005
1134
  const createStampId = runtime.incrementId();
1006
1135
  let launchStampId = createStampId();
1007
1136
  function createRouter(app, config, framework) {
1008
1137
  var _a, _b;
1138
+ if (typeof app.onUnhandledRejection === 'function') {
1139
+ window.addEventListener('unhandledrejection', app.onUnhandledRejection);
1140
+ }
1009
1141
  RouterConfig.config = config;
1010
1142
  const handler = new PageHandler(config);
1011
1143
  routesAlias.set(handler.router.customRoutes);
@@ -1030,8 +1162,10 @@ function createRouter(app, config, framework) {
1030
1162
  (_a = app.onLaunch) === null || _a === void 0 ? void 0 : _a.call(app, launchParam);
1031
1163
  app.onError && window.addEventListener('error', e => { var _a; return (_a = app.onError) === null || _a === void 0 ? void 0 : _a.call(app, e.message); });
1032
1164
  const render = ({ location, action }) => __awaiter(this, void 0, void 0, function* () {
1033
- var _c, _d, _e, _f, _g;
1165
+ var _c, _d, _e, _f, _g, _h;
1034
1166
  handler.pathname = decodeURI(location.pathname);
1167
+ if ((_c = window.__taroAppConfig) === null || _c === void 0 ? void 0 : _c.usingWindowScroll)
1168
+ window.scrollTo(0, 0);
1035
1169
  runtime.eventCenter.trigger('__taroRouterChange', {
1036
1170
  toLocation: {
1037
1171
  path: handler.pathname
@@ -1044,9 +1178,13 @@ function createRouter(app, config, framework) {
1044
1178
  }
1045
1179
  catch (error) {
1046
1180
  if (error.status === 404) {
1047
- (_c = app.onPageNotFound) === null || _c === void 0 ? void 0 : _c.call(app, {
1048
- path: handler.pathname
1049
- });
1181
+ const notFoundEvent = {
1182
+ isEntryPage: stacks.length === 0,
1183
+ path: handler.pathname,
1184
+ query: handler.getQuery(createStampId()),
1185
+ };
1186
+ (_d = app.onPageNotFound) === null || _d === void 0 ? void 0 : _d.call(app, notFoundEvent);
1187
+ runtime.eventCenter.trigger('__taroRouterNotFound', notFoundEvent);
1050
1188
  }
1051
1189
  else if (/Loading hot update .* failed./.test(error.message)) {
1052
1190
  // NOTE: webpack5 与 prebundle 搭配使用时,开发环境下初次启动时偶发错误,由于 HMR 加载 chunk hash 错误,导致热更新失败
@@ -1059,16 +1197,16 @@ function createRouter(app, config, framework) {
1059
1197
  if (!element)
1060
1198
  return;
1061
1199
  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;
1200
+ let enablePullDownRefresh = ((_e = config === null || config === void 0 ? void 0 : config.window) === null || _e === void 0 ? void 0 : _e.enablePullDownRefresh) || false;
1063
1201
  if (pageConfig) {
1064
- setTitle((_e = pageConfig.navigationBarTitleText) !== null && _e !== void 0 ? _e : document.title);
1202
+ setTitle((_f = pageConfig.navigationBarTitleText) !== null && _f !== void 0 ? _f : document.title);
1065
1203
  if (typeof pageConfig.enablePullDownRefresh === 'boolean') {
1066
1204
  enablePullDownRefresh = pageConfig.enablePullDownRefresh;
1067
1205
  }
1068
1206
  }
1069
1207
  const currentPage = runtime.Current.page;
1070
1208
  const pathname = handler.pathname;
1071
- const methodName = (_f = stacks.method) !== null && _f !== void 0 ? _f : '';
1209
+ const methodName = (_g = stacks.method) !== null && _g !== void 0 ? _g : '';
1072
1210
  const cacheTabs = stacks.getTabs();
1073
1211
  let shouldLoad = false;
1074
1212
  stacks.method = '';
@@ -1093,11 +1231,11 @@ function createRouter(app, config, framework) {
1093
1231
  else if (stacks.length > 0) {
1094
1232
  const firstIns = stacks.getItem(0);
1095
1233
  if (handler.isTabBar(firstIns.path)) {
1096
- handler.unload(currentPage, stacks.length - 1);
1234
+ handler.unload(currentPage, stacks.length - 1, true);
1097
1235
  stacks.pushTab(firstIns.path.split('?')[0]);
1098
1236
  }
1099
1237
  else {
1100
- handler.unload(currentPage, stacks.length);
1238
+ handler.unload(currentPage, stacks.length, true);
1101
1239
  }
1102
1240
  }
1103
1241
  if (cacheTabs[handler.pathname]) {
@@ -1114,7 +1252,9 @@ function createRouter(app, config, framework) {
1114
1252
  if (currentPage !== stacks.getItem(prevIndex)) {
1115
1253
  handler.unload(currentPage, delta, prevIndex > -1);
1116
1254
  if (prevIndex > -1) {
1117
- handler.show(stacks.getItem(prevIndex), pageConfig, prevIndex);
1255
+ runtime.eventCenter.once('__taroPageOnShowAfterDestroyed', () => {
1256
+ handler.show(stacks.getItem(prevIndex), pageConfig, prevIndex);
1257
+ });
1118
1258
  }
1119
1259
  else {
1120
1260
  shouldLoad = true;
@@ -1132,7 +1272,7 @@ function createRouter(app, config, framework) {
1132
1272
  shouldLoad = true;
1133
1273
  }
1134
1274
  if (shouldLoad || stacks.length < 1) {
1135
- const el = (_g = element.default) !== null && _g !== void 0 ? _g : element;
1275
+ const el = (_h = element.default) !== null && _h !== void 0 ? _h : element;
1136
1276
  const loadConfig = Object.assign({}, pageConfig);
1137
1277
  const stacksIndex = stacks.length;
1138
1278
  delete loadConfig['path'];
@@ -1145,16 +1285,11 @@ function createRouter(app, config, framework) {
1145
1285
  else {
1146
1286
  pageStampId = createStampId();
1147
1287
  }
1148
- const page = runtime.createPageConfig(enablePullDownRefresh ? runtime.hooks.call('createPullDownComponent', el, location.pathname, framework, handler.PullDownRefresh) : el, pathname + runtime.stringify(handler.getQuery(pageStampId)), {}, loadConfig);
1288
+ const page = runtime.createPageConfig(enablePullDownRefresh ? runtime.hooks.call('createPullDownComponent', el, pathname, framework, handler.PullDownRefresh, pageStampId) : el, pathname + runtime.stringify(handler.getQuery(pageStampId)), {}, loadConfig);
1149
1289
  if (params)
1150
1290
  page.options = params;
1151
1291
  handler.load(page, pageConfig, pageStampId, stacksIndex);
1152
1292
  }
1153
- runtime.eventCenter.trigger('__afterTaroRouterChange', {
1154
- toLocation: {
1155
- path: handler.pathname
1156
- }
1157
- });
1158
1293
  });
1159
1294
  const routePath = addLeadingSlash(stripBasename(exports.history.location.pathname, handler.basename));
1160
1295
  if (routePath === '/') {