@tarojs/router 3.3.17 → 3.3.18

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.
@@ -1,4 +1,4 @@
1
- import { requestAnimationFrame, container, SERVICE_IDENTIFIER, eventCenter, Current, createPageConfig, stringify } from '@tarojs/runtime';
1
+ import { Current, requestAnimationFrame, container, SERVICE_IDENTIFIER, eventCenter, createPageConfig, stringify } from '@tarojs/runtime';
2
2
  import { initTabBarApis } from '@tarojs/taro';
3
3
 
4
4
  function _extends() {
@@ -49,8 +49,8 @@ function setHistoryMode(mode, base = '/') {
49
49
  function prependBasename(url = '') {
50
50
  return basename.replace(/\/$/, '') + '/' + url.replace(/^\//, '');
51
51
  }
52
- const hasBasename = (path, prefix) => new RegExp('^' + prefix + '(\\/|\\?|#|$)', 'i').test(path);
53
- const stripBasename = (path, prefix) => hasBasename(path, prefix) ? path.substr(prefix.length) : path;
52
+ const hasBasename = (path = '', prefix = '') => new RegExp('^' + prefix + '(\\/|\\?|#|$)', 'i').test(path);
53
+ const stripBasename = (path = '', prefix = '') => hasBasename(path, prefix) ? path.substr(prefix.length) : path;
54
54
 
55
55
  class Stacks {
56
56
  constructor() {
@@ -77,9 +77,9 @@ class Stacks {
77
77
  getItem(index) {
78
78
  return this.stacks[index];
79
79
  }
80
- getLastIndex(pathname) {
80
+ getLastIndex(pathname, stateWith = 1) {
81
81
  const list = [...this.stacks].reverse();
82
- return list.findIndex((page, i) => { var _a; return i !== 0 && ((_a = page.path) === null || _a === void 0 ? void 0 : _a.replace(/\?.*/g, '')) === pathname; });
82
+ return list.findIndex((page, i) => { var _a; return i >= stateWith && ((_a = page.path) === null || _a === void 0 ? void 0 : _a.replace(/\?.*/g, '')) === pathname; });
83
83
  }
84
84
  getDelta(pathname) {
85
85
  if (this.backDelta >= 1) {
@@ -88,8 +88,8 @@ class Stacks {
88
88
  // NOTE: 此处为了修复浏览器后退多级页面,在大量重复路由状况下可能出现判断错误的情况 (增强判断能力只能考虑在 query 中新增参数来判断,暂时搁置)
89
89
  return this.getLastIndex(pathname) || 1;
90
90
  }
91
- getPrevIndex(pathname) {
92
- const lastIndex = this.getLastIndex(pathname);
91
+ getPrevIndex(pathname, stateWith = 1) {
92
+ const lastIndex = this.getLastIndex(pathname, stateWith);
93
93
  if (lastIndex < 0) {
94
94
  return -1;
95
95
  }
@@ -113,21 +113,21 @@ function addLeadingSlash(path) {
113
113
  class RoutesAlias {
114
114
  constructor() {
115
115
  this.conf = [];
116
- this.getConfig = (url) => {
116
+ this.getConfig = (url = '') => {
117
117
  const customRoute = this.conf.filter((arr) => {
118
118
  return arr.includes(url);
119
119
  });
120
120
  return customRoute[0];
121
121
  };
122
- this.getOrigin = (url) => {
122
+ this.getOrigin = (url = '') => {
123
123
  var _a;
124
124
  return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[0]) || url;
125
125
  };
126
- this.getAlias = (url) => {
126
+ this.getAlias = (url = '') => {
127
127
  var _a;
128
128
  return ((_a = this.getConfig(url)) === null || _a === void 0 ? void 0 : _a[1]) || url;
129
129
  };
130
- this.getAll = (url) => {
130
+ this.getAll = (url = '') => {
131
131
  return this.conf.filter((arr) => {
132
132
  return arr.includes(url);
133
133
  }).reduce((p, a) => {
@@ -149,22 +149,7 @@ class RoutesAlias {
149
149
  }
150
150
  }
151
151
  }
152
- const routesAlias = new RoutesAlias();
153
- const isTabBar = (config) => {
154
- var _a, _b;
155
- const { customRoutes = {}, basename = '', pathname } = config.router;
156
- const routePath = stripBasename(pathname, basename);
157
- const pagePath = ((_a = Object.entries(customRoutes).find(([, target]) => {
158
- if (typeof target === 'string') {
159
- return target === routePath;
160
- }
161
- else if ((target === null || target === void 0 ? void 0 : target.length) > 0) {
162
- return target.includes(routePath);
163
- }
164
- return false;
165
- })) === null || _a === void 0 ? void 0 : _a[0]) || routePath;
166
- return !!pagePath && (((_b = config.tabBar) === null || _b === void 0 ? void 0 : _b.list) || []).some(t => t.pagePath === pagePath);
167
- };
152
+ const routesAlias = new RoutesAlias();
168
153
 
169
154
  function processNavigateUrl(option) {
170
155
  var _a;
@@ -894,108 +879,6 @@ var UniversalRouter = function () {
894
879
 
895
880
  UniversalRouter.pathToRegexp = pathToRegexp_1;
896
881
 
897
- // @ts-nocheck
898
- function initTabbar(config) {
899
- if (config.tabBar == null) {
900
- return;
901
- }
902
- // TODO: 找到 tabbar 的类型
903
- const tabbar = document.createElement('taro-tabbar');
904
- const homePage = config.entryPagePath || (config.pages ? config.pages[0] : '');
905
- tabbar.conf = config.tabBar;
906
- tabbar.conf.homePage = history.location.pathname === '/' ? homePage : history.location.pathname;
907
- const routerConfig = config.router;
908
- tabbar.conf.mode = routerConfig && routerConfig.mode ? routerConfig.mode : 'hash';
909
- if (routerConfig.customRoutes) {
910
- tabbar.conf.custom = true;
911
- tabbar.conf.customRoutes = routerConfig.customRoutes;
912
- }
913
- else {
914
- tabbar.conf.custom = false;
915
- tabbar.conf.customRoutes = {};
916
- }
917
- if (typeof routerConfig.basename !== 'undefined') {
918
- tabbar.conf.basename = routerConfig.basename;
919
- }
920
- const container = document.getElementById('container');
921
- // eslint-disable-next-line no-unused-expressions
922
- container === null || container === void 0 ? void 0 : container.appendChild(tabbar);
923
- initTabBarApis(config);
924
- }
925
-
926
- const routerConfig = Object.create(null);
927
- function init(config) {
928
- var _a;
929
- config.router.mode = config.router.mode || 'hash';
930
- setHistoryMode(config.router.mode, config.router.basename);
931
- Object.assign(routerConfig, config);
932
- (_a = document.getElementById('app')) === null || _a === void 0 ? void 0 : _a.remove();
933
- const container = document.createElement('div');
934
- container.classList.add('taro-tabbar__container');
935
- container.id = 'container';
936
- const panel = document.createElement('div');
937
- panel.classList.add('taro-tabbar__panel');
938
- const app = document.createElement('div');
939
- app.id = 'app';
940
- app.classList.add('taro_router');
941
- panel.appendChild(app);
942
- container.appendChild(panel);
943
- document.body.appendChild(container);
944
- initTabbar(config);
945
- }
946
-
947
- let pageScrollFn;
948
- let pageDOM = window;
949
- function bindPageScroll(page, config) {
950
- pageDOM.removeEventListener('scroll', pageScrollFn);
951
- pageDOM = getScrollContainer();
952
- const distance = config.onReachBottomDistance || 50;
953
- let isReachBottom = false;
954
- pageScrollFn = function () {
955
- page.onPageScroll && page.onPageScroll({
956
- scrollTop: pageDOM instanceof Window ? window.scrollY : pageDOM.scrollTop
957
- });
958
- if (isReachBottom && getOffset() > distance) {
959
- isReachBottom = false;
960
- }
961
- if (page.onReachBottom &&
962
- !isReachBottom &&
963
- getOffset() < distance) {
964
- isReachBottom = true;
965
- page.onReachBottom();
966
- }
967
- };
968
- pageDOM.addEventListener('scroll', pageScrollFn, false);
969
- }
970
- window.addEventListener('DOMSubtreeModified', (e) => {
971
- var _a;
972
- // @ts-ignore
973
- const className = (_a = e.target) === null || _a === void 0 ? void 0 : _a.className;
974
- if (className && /taro-tabbar__/.test(className)) {
975
- pageDOM.removeEventListener('scroll', pageScrollFn);
976
- pageDOM = getScrollContainer();
977
- pageDOM.addEventListener('scroll', pageScrollFn, false);
978
- }
979
- }, false);
980
- function getScrollContainer() {
981
- if (document.querySelector('.taro-tabbar__tabbar') === null) {
982
- // 没设置tabbar
983
- return window;
984
- }
985
- else {
986
- // 有设置tabbar
987
- return document.querySelector('.taro-tabbar__panel') || window;
988
- }
989
- }
990
- function getOffset() {
991
- if (pageDOM instanceof Window) {
992
- return document.documentElement.scrollHeight - window.scrollY - window.innerHeight;
993
- }
994
- else {
995
- return pageDOM.scrollHeight - pageDOM.scrollTop - pageDOM.clientHeight;
996
- }
997
- }
998
-
999
882
  function createCommonjsModule(fn, module) {
1000
883
  return module = { exports: {} }, fn(module, module.exports), module.exports;
1001
884
  }
@@ -1547,124 +1430,360 @@ var queryString_5 = queryString.stringifyUrl;
1547
1430
  var queryString_6 = queryString.pick;
1548
1431
  var queryString_7 = queryString.exclude;
1549
1432
 
1550
- function getSearch() {
1551
- let search = '?';
1552
- if (routerConfig.router.mode === 'hash') {
1553
- const idx = location.hash.indexOf('?');
1554
- if (idx > -1) {
1555
- search = location.hash.slice(idx);
1433
+ let pageScrollFn;
1434
+ let pageDOM = window;
1435
+ function bindPageScroll(page, config) {
1436
+ pageDOM.removeEventListener('scroll', pageScrollFn);
1437
+ pageDOM = getScrollContainer();
1438
+ const distance = config.onReachBottomDistance || 50;
1439
+ let isReachBottom = false;
1440
+ pageScrollFn = function () {
1441
+ page.onPageScroll && page.onPageScroll({
1442
+ scrollTop: pageDOM instanceof Window ? window.scrollY : pageDOM.scrollTop
1443
+ });
1444
+ if (isReachBottom && getOffset() > distance) {
1445
+ isReachBottom = false;
1556
1446
  }
1557
- }
1558
- else {
1559
- search = location.search;
1560
- }
1561
- return search.substr(1);
1447
+ if (page.onReachBottom &&
1448
+ !isReachBottom &&
1449
+ getOffset() < distance) {
1450
+ isReachBottom = true;
1451
+ page.onReachBottom();
1452
+ }
1453
+ };
1454
+ pageDOM.addEventListener('scroll', pageScrollFn, false);
1562
1455
  }
1563
- const qs = function (stamp = 0) {
1564
- const search = getSearch();
1565
- const query = search
1566
- ? queryString.parse(search)
1567
- : {};
1568
- if (stamp) {
1569
- query.stamp = stamp.toString();
1570
- }
1571
- return query;
1572
- };
1573
-
1574
- /* eslint-disable dot-notation */
1575
- function pageOnReady(page, onLoad = true) {
1576
- var _a, _b;
1577
- const pageEl = document.getElementById(page.path);
1578
- if (pageEl && !(pageEl === null || pageEl === void 0 ? void 0 : pageEl['__isReady'])) {
1579
- const el = pageEl.firstElementChild;
1580
- (_b = (_a = el === null || el === void 0 ? void 0 : el['componentOnReady']) === null || _a === void 0 ? void 0 : _a.call(el)) === null || _b === void 0 ? void 0 : _b.then(() => {
1581
- requestAnimationFrame(() => {
1582
- page.onReady();
1583
- pageEl['__isReady'] = true;
1584
- });
1585
- });
1586
- onLoad && (pageEl['__page'] = page);
1456
+ window.addEventListener('DOMSubtreeModified', (e) => {
1457
+ const target = e.target;
1458
+ const className = target === null || target === void 0 ? void 0 : target.className;
1459
+ if (className && /taro_page/.test(className)) {
1460
+ pageDOM.removeEventListener('scroll', pageScrollFn);
1461
+ pageDOM = getScrollContainer();
1462
+ pageDOM.addEventListener('scroll', pageScrollFn, false);
1587
1463
  }
1464
+ }, false);
1465
+ function getScrollContainer() {
1466
+ var _a;
1467
+ const id = (_a = Current.page) === null || _a === void 0 ? void 0 : _a.path;
1468
+ const el = (id
1469
+ ? document.getElementById(id)
1470
+ : document.querySelector('.taro_page') ||
1471
+ document.querySelector('.taro_router'));
1472
+ return el || window;
1588
1473
  }
1589
- function loadPage(page, pageConfig = {}, stacksIndex = 0) {
1590
- if (!page)
1591
- return;
1592
- const pageEl = document.getElementById(page.path);
1593
- if (pageEl) {
1594
- pageEl.style.display = 'block';
1474
+ function getOffset() {
1475
+ if (pageDOM instanceof Window) {
1476
+ return document.documentElement.scrollHeight - window.scrollY - window.innerHeight;
1595
1477
  }
1596
1478
  else {
1597
- page.onLoad(qs(stacksIndex), () => pageOnReady(page, true));
1479
+ return pageDOM.scrollHeight - pageDOM.scrollTop - pageDOM.clientHeight;
1598
1480
  }
1599
- stacks.push(page);
1600
- page.onShow();
1601
- bindPageScroll(page, pageConfig);
1602
- }
1603
- function unloadPage(page, delta = 1) {
1604
- if (!page)
1605
- return;
1606
- stacks.delta = --delta;
1607
- stacks.pop();
1608
- page.onUnload();
1609
- if (delta >= 1)
1610
- unloadPage(stacks.last, delta);
1611
- }
1612
- function showPage(page, pageConfig = {}, stacksIndex = 0) {
1613
- if (!page)
1481
+ }
1482
+
1483
+ /**
1484
+ * 插入页面动画需要的样式
1485
+ */
1486
+ function loadAnimateStyle(ms = 300) {
1487
+ const css = `
1488
+ .taro_router .taro_page {
1489
+ position: absolute;
1490
+ left: 0;
1491
+ top: 0;
1492
+ width: 100%;
1493
+ height: 100%;
1494
+ transform: translate3d(100%, 0, 0);
1495
+ transition: transform ${ms}ms;
1496
+ }
1497
+
1498
+ .taro_router .taro_page.taro_tabbar_page {
1499
+ transform: none;
1500
+ }
1501
+
1502
+ .taro_router .taro_page.taro_page_show {
1503
+ transform: translate3d(0, 0, 0);
1504
+ }`;
1505
+ const style = document.createElement('style');
1506
+ style.innerHTML = css;
1507
+ document.getElementsByTagName('head')[0].appendChild(style);
1508
+ }
1509
+
1510
+ // @ts-nocheck
1511
+ function initTabbar(config) {
1512
+ if (config.tabBar == null) {
1614
1513
  return;
1615
- page.onShow();
1616
- const pageEl = document.getElementById(page.path);
1617
- if (pageEl) {
1618
- pageEl.style.display = 'block';
1514
+ }
1515
+ // TODO: custom-tab-bar
1516
+ const tabbar = document.createElement('taro-tabbar');
1517
+ const homePage = config.entryPagePath || (config.pages ? config.pages[0] : '');
1518
+ tabbar.conf = config.tabBar;
1519
+ tabbar.conf.homePage = history.location.pathname === '/' ? homePage : history.location.pathname;
1520
+ const routerConfig = config.router;
1521
+ tabbar.conf.mode = routerConfig && routerConfig.mode ? routerConfig.mode : 'hash';
1522
+ if (routerConfig.customRoutes) {
1523
+ tabbar.conf.custom = true;
1524
+ tabbar.conf.customRoutes = routerConfig.customRoutes;
1619
1525
  }
1620
1526
  else {
1621
- page.onLoad(qs(stacksIndex), () => pageOnReady(page, false));
1527
+ tabbar.conf.custom = false;
1528
+ tabbar.conf.customRoutes = {};
1529
+ }
1530
+ if (typeof routerConfig.basename !== 'undefined') {
1531
+ tabbar.conf.basename = routerConfig.basename;
1532
+ }
1533
+ const container = document.getElementById('container');
1534
+ container === null || container === void 0 ? void 0 : container.appendChild(tabbar);
1535
+ initTabBarApis(config);
1536
+ }
1537
+
1538
+ function setDisplay(el, type = '') {
1539
+ if (el) {
1540
+ el.style.display = type;
1622
1541
  }
1623
- bindPageScroll(page, pageConfig);
1624
1542
  }
1625
- function hidePage(page) {
1626
- if (!page)
1627
- return;
1628
- // NOTE: 修复多页并发问题,此处可能因为路由跳转过快,执行时页面可能还没有创建成功
1629
- const pageEl = document.getElementById(page.path);
1630
- if (pageEl) {
1631
- pageEl.style.display = 'none';
1632
- page.onHide();
1543
+ class PageHandler {
1544
+ constructor(config) {
1545
+ this.defaultAnimation = { duration: 300, delay: 50 };
1546
+ this.config = config;
1547
+ this.mount();
1633
1548
  }
1634
- else {
1635
- setTimeout(() => hidePage(page), 0);
1549
+ get appId() { return 'app'; }
1550
+ get router() { return this.config.router; }
1551
+ get routerMode() { return this.router.mode || 'hash'; }
1552
+ get customRoutes() { return this.router.customRoutes || {}; }
1553
+ get routes() { return this.config.routes; }
1554
+ get tabBarList() { var _a; return ((_a = this.config.tabBar) === null || _a === void 0 ? void 0 : _a.list) || []; }
1555
+ get PullDownRefresh() { return this.config.PullDownRefresh; }
1556
+ get animation() { var _a, _b; return (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.animation) !== null && _b !== void 0 ? _b : this.defaultAnimation; }
1557
+ get animationDelay() {
1558
+ var _a;
1559
+ return typeof this.animation === 'object'
1560
+ ? this.animation.delay
1561
+ : this.animation
1562
+ ? (_a = this.defaultAnimation) === null || _a === void 0 ? void 0 : _a.delay
1563
+ : 0;
1564
+ }
1565
+ get animationDuration() {
1566
+ var _a;
1567
+ return typeof this.animation === 'object'
1568
+ ? this.animation.duration
1569
+ : this.animation
1570
+ ? (_a = this.defaultAnimation) === null || _a === void 0 ? void 0 : _a.duration
1571
+ : 0;
1572
+ }
1573
+ set pathname(p) { this.router.pathname = p; }
1574
+ get pathname() { return this.router.pathname; }
1575
+ get basename() { return this.router.basename || ''; }
1576
+ get pageConfig() {
1577
+ return this.routes.find(r => {
1578
+ var _a;
1579
+ const routePath = stripBasename(this.pathname, this.basename);
1580
+ const pagePath = addLeadingSlash(r.path);
1581
+ return pagePath === routePath || ((_a = routesAlias.getConfig(pagePath)) === null || _a === void 0 ? void 0 : _a.includes(routePath));
1582
+ });
1583
+ }
1584
+ get isTabBar() {
1585
+ var _a;
1586
+ const routePath = stripBasename(this.pathname, this.basename);
1587
+ const pagePath = ((_a = Object.entries(this.customRoutes).find(([, target]) => {
1588
+ if (typeof target === 'string') {
1589
+ return target === routePath;
1590
+ }
1591
+ else if ((target === null || target === void 0 ? void 0 : target.length) > 0) {
1592
+ return target.includes(routePath);
1593
+ }
1594
+ return false;
1595
+ })) === null || _a === void 0 ? void 0 : _a[0]) || routePath;
1596
+ return !!pagePath && this.tabBarList.some(t => t.pagePath === pagePath);
1597
+ }
1598
+ isSamePage(page) {
1599
+ const routePath = stripBasename(this.pathname, this.basename);
1600
+ const pagePath = stripBasename(page === null || page === void 0 ? void 0 : page.path, this.basename);
1601
+ return pagePath.startsWith(routePath + '?');
1602
+ }
1603
+ get search() {
1604
+ let search = '?';
1605
+ if (this.routerMode) {
1606
+ const idx = location.hash.indexOf('?');
1607
+ if (idx > -1) {
1608
+ search = location.hash.slice(idx);
1609
+ }
1610
+ }
1611
+ else {
1612
+ search = location.search;
1613
+ }
1614
+ return search.substr(1);
1615
+ }
1616
+ getQuery(stamp = 0) {
1617
+ const search = this.search;
1618
+ const query = search
1619
+ ? queryString.parse(search)
1620
+ : {};
1621
+ if (stamp) {
1622
+ query.stamp = stamp.toString();
1623
+ }
1624
+ return query;
1625
+ }
1626
+ mount() {
1627
+ var _a;
1628
+ setHistoryMode(this.routerMode, this.router.basename);
1629
+ (_a = document.getElementById('app')) === null || _a === void 0 ? void 0 : _a.remove();
1630
+ this.animation && loadAnimateStyle(this.animationDuration);
1631
+ const app = document.createElement('div');
1632
+ app.id = this.appId;
1633
+ app.classList.add('taro_router');
1634
+ if (this.tabBarList.length > 1) {
1635
+ const container = document.createElement('div');
1636
+ container.classList.add('taro-tabbar__container');
1637
+ container.id = 'container';
1638
+ const panel = document.createElement('div');
1639
+ panel.classList.add('taro-tabbar__panel');
1640
+ panel.appendChild(app);
1641
+ container.appendChild(panel);
1642
+ document.body.appendChild(container);
1643
+ initTabbar(this.config);
1644
+ }
1645
+ else {
1646
+ document.body.appendChild(app);
1647
+ }
1648
+ }
1649
+ onReady(page, onLoad = true) {
1650
+ var _a, _b;
1651
+ const pageEl = document.getElementById(page.path);
1652
+ if (pageEl && !(pageEl === null || pageEl === void 0 ? void 0 : pageEl['__isReady'])) {
1653
+ const el = pageEl.firstElementChild;
1654
+ (_b = (_a = el === null || el === void 0 ? void 0 : el['componentOnReady']) === null || _a === void 0 ? void 0 : _a.call(el)) === null || _b === void 0 ? void 0 : _b.then(() => {
1655
+ requestAnimationFrame(() => {
1656
+ page.onReady();
1657
+ pageEl['__isReady'] = true;
1658
+ });
1659
+ });
1660
+ onLoad && (pageEl['__page'] = page);
1661
+ }
1662
+ }
1663
+ load(page, pageConfig = {}, stacksIndex = 0) {
1664
+ if (!page)
1665
+ return;
1666
+ let pageEl = document.getElementById(page.path);
1667
+ if (pageEl) {
1668
+ setDisplay(pageEl);
1669
+ this.isTabBar && pageEl.classList.add('taro_tabbar_page');
1670
+ this.addAnimation(pageEl, stacksIndex === 0);
1671
+ }
1672
+ else {
1673
+ page.onLoad(this.getQuery(stacksIndex), () => {
1674
+ pageEl = document.getElementById(page.path);
1675
+ this.isTabBar && (pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.add('taro_tabbar_page'));
1676
+ this.addAnimation(pageEl, stacksIndex === 0);
1677
+ this.onReady(page, true);
1678
+ });
1679
+ }
1680
+ stacks.push(page);
1681
+ page.onShow();
1682
+ bindPageScroll(page, pageConfig);
1683
+ }
1684
+ unload(page, delta = 1, top = false) {
1685
+ var _a;
1686
+ if (!page)
1687
+ return;
1688
+ stacks.delta = --delta;
1689
+ stacks.pop();
1690
+ if (this.animation && top) {
1691
+ if (this.unloadTimer) {
1692
+ clearTimeout(this.unloadTimer);
1693
+ (_a = this.lastUnloadPage) === null || _a === void 0 ? void 0 : _a.onUnload();
1694
+ this.unloadTimer = null;
1695
+ }
1696
+ this.lastUnloadPage = page;
1697
+ const pageEl = document.getElementById(page.path);
1698
+ pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_show');
1699
+ this.unloadTimer = setTimeout(() => {
1700
+ var _a;
1701
+ this.unloadTimer = null;
1702
+ (_a = this.lastUnloadPage) === null || _a === void 0 ? void 0 : _a.onUnload();
1703
+ }, this.animationDuration);
1704
+ }
1705
+ if (delta >= 1)
1706
+ this.unload(stacks.last, delta);
1707
+ }
1708
+ show(page, pageConfig = {}, stacksIndex = 0) {
1709
+ if (!page)
1710
+ return;
1711
+ page.onShow();
1712
+ let pageEl = document.getElementById(page.path);
1713
+ if (pageEl) {
1714
+ setDisplay(pageEl);
1715
+ this.addAnimation(pageEl, stacksIndex === 0);
1716
+ }
1717
+ else {
1718
+ page.onLoad(this.getQuery(stacksIndex), () => {
1719
+ pageEl = document.getElementById(page.path);
1720
+ this.addAnimation(pageEl, stacksIndex === 0);
1721
+ this.onReady(page, false);
1722
+ });
1723
+ }
1724
+ bindPageScroll(page, pageConfig);
1725
+ }
1726
+ hide(page) {
1727
+ if (!page)
1728
+ return;
1729
+ // NOTE: 修复多页并发问题,此处可能因为路由跳转过快,执行时页面可能还没有创建成功
1730
+ const pageEl = document.getElementById(page.path);
1731
+ if (pageEl) {
1732
+ if (this.hideTimer) {
1733
+ clearTimeout(this.hideTimer);
1734
+ this.hideTimer = null;
1735
+ setDisplay(this.lastHidePage, 'none');
1736
+ }
1737
+ this.lastHidePage = pageEl;
1738
+ this.hideTimer = setTimeout(() => {
1739
+ this.hideTimer = null;
1740
+ setDisplay(this.lastHidePage, 'none');
1741
+ }, this.animationDelay);
1742
+ page.onHide();
1743
+ }
1744
+ else {
1745
+ setTimeout(() => this.hide(page), 0);
1746
+ }
1747
+ }
1748
+ addAnimation(pageEl, first = false) {
1749
+ if (!pageEl)
1750
+ return;
1751
+ if (this.animation && !first) {
1752
+ setTimeout(() => {
1753
+ pageEl.classList.add('taro_page_show');
1754
+ }, this.animationDelay);
1755
+ }
1756
+ else {
1757
+ pageEl.classList.add('taro_page_show');
1758
+ }
1636
1759
  }
1637
1760
  }
1638
1761
 
1639
1762
  /* eslint-disable dot-notation */
1640
1763
  function createRouter(app, config, framework) {
1641
1764
  var _a;
1642
- init(config);
1643
- const routes = [];
1765
+ const handler = new PageHandler(config);
1644
1766
  const runtimeHooks = container.get(SERVICE_IDENTIFIER.Hooks);
1645
- routesAlias.set(config.router.customRoutes);
1646
- for (let i = 0; i < config.routes.length; i++) {
1647
- const route = config.routes[i];
1648
- const path = addLeadingSlash(route.path);
1649
- routes.push({
1650
- path: routesAlias.getAll(path),
1651
- action: route.load
1652
- });
1653
- }
1654
- const basename = config.router.basename;
1767
+ routesAlias.set(handler.router.customRoutes);
1768
+ const basename = handler.router.basename;
1769
+ const routes = handler.routes.map(route => ({
1770
+ path: routesAlias.getAll(addLeadingSlash(route.path)),
1771
+ action: route.load
1772
+ }));
1773
+ const entryPagePath = config.entryPagePath || ((_a = routes[0].path) === null || _a === void 0 ? void 0 : _a[0]);
1655
1774
  const router = new UniversalRouter(routes, { baseUrl: basename || '' });
1656
1775
  app.onLaunch();
1657
1776
  const render = async ({ location, action }) => {
1658
1777
  var _a, _b, _c, _d;
1659
- routerConfig.router.pathname = location.pathname;
1778
+ handler.pathname = location.pathname;
1660
1779
  let element;
1661
1780
  try {
1662
- element = await router.resolve(config.router.forcePath || location.pathname);
1781
+ element = await router.resolve(handler.router.forcePath || handler.pathname);
1663
1782
  }
1664
1783
  catch (error) {
1665
1784
  if (error.status === 404) {
1666
1785
  (_a = app.onPageNotFound) === null || _a === void 0 ? void 0 : _a.call(app, {
1667
- path: location.pathname
1786
+ path: handler.pathname
1668
1787
  });
1669
1788
  }
1670
1789
  else {
@@ -1673,16 +1792,11 @@ function createRouter(app, config, framework) {
1673
1792
  }
1674
1793
  if (!element)
1675
1794
  return;
1676
- const pageConfig = config.routes.find(r => {
1677
- var _a;
1678
- const path = addLeadingSlash(r.path);
1679
- const urlPath = stripBasename(location.pathname, routerConfig.router.basename);
1680
- return path === urlPath || ((_a = routesAlias.getConfig(path)) === null || _a === void 0 ? void 0 : _a.includes(urlPath));
1681
- });
1795
+ const pageConfig = handler.pageConfig;
1682
1796
  let enablePullDownRefresh = false;
1683
1797
  eventCenter.trigger('__taroRouterChange', {
1684
1798
  toLocation: {
1685
- path: location.pathname
1799
+ path: handler.pathname
1686
1800
  }
1687
1801
  });
1688
1802
  if (pageConfig) {
@@ -1690,37 +1804,38 @@ function createRouter(app, config, framework) {
1690
1804
  enablePullDownRefresh = pageConfig.enablePullDownRefresh;
1691
1805
  }
1692
1806
  const currentPage = Current.page;
1693
- const pathname = location.pathname;
1807
+ const pathname = handler.pathname;
1694
1808
  let shouldLoad = false;
1695
1809
  if (action === 'POP') {
1696
1810
  // NOTE: 浏览器事件退后多次时,该事件只会被触发一次
1697
1811
  const prevIndex = stacks.getPrevIndex(pathname);
1698
1812
  const delta = stacks.getDelta(pathname);
1699
- unloadPage(currentPage, delta);
1813
+ handler.unload(currentPage, delta, prevIndex > -1);
1700
1814
  if (prevIndex > -1) {
1701
- showPage(stacks.getItem(prevIndex), pageConfig, prevIndex);
1815
+ handler.show(stacks.getItem(prevIndex), pageConfig, prevIndex);
1702
1816
  }
1703
1817
  else {
1704
1818
  shouldLoad = true;
1705
1819
  }
1706
1820
  }
1707
- else if (action === 'PUSH') {
1708
- hidePage(currentPage);
1709
- shouldLoad = true;
1710
- }
1711
- else if (action === 'REPLACE') {
1712
- if (isTabBar(config)) {
1713
- hidePage(currentPage);
1714
- const prevIndex = stacks.getPrevIndex(pathname);
1821
+ else {
1822
+ if (handler.isTabBar) {
1823
+ if (handler.isSamePage(currentPage))
1824
+ return;
1825
+ const prevIndex = stacks.getPrevIndex(pathname, 0);
1826
+ handler.hide(currentPage);
1715
1827
  if (prevIndex > -1) {
1716
1828
  // NOTE: tabbar 页且之前出现过,直接复用
1717
- return showPage(stacks.getItem(prevIndex), pageConfig, prevIndex);
1829
+ return handler.show(stacks.getItem(prevIndex), pageConfig, prevIndex);
1718
1830
  }
1719
1831
  }
1720
- else {
1832
+ else if (action === 'REPLACE') {
1721
1833
  const delta = stacks.getDelta(pathname);
1722
1834
  // NOTE: 页面路由记录并不会清空,只是移除掉缓存的 stack 以及页面
1723
- unloadPage(currentPage, delta);
1835
+ handler.unload(currentPage, delta);
1836
+ }
1837
+ else if (action === 'PUSH') {
1838
+ handler.hide(currentPage);
1724
1839
  }
1725
1840
  shouldLoad = true;
1726
1841
  }
@@ -1730,15 +1845,15 @@ function createRouter(app, config, framework) {
1730
1845
  const stacksIndex = stacks.length;
1731
1846
  delete loadConfig['path'];
1732
1847
  delete loadConfig['load'];
1733
- const page = createPageConfig(enablePullDownRefresh ? (_d = runtimeHooks.createPullDownComponent) === null || _d === void 0 ? void 0 : _d.call(runtimeHooks, el, location.pathname, framework, routerConfig.PullDownRefresh) : el, pathname + stringify(qs(stacksIndex)), {}, loadConfig);
1734
- return loadPage(page, pageConfig, stacksIndex);
1848
+ const page = createPageConfig(enablePullDownRefresh ? (_d = runtimeHooks.createPullDownComponent) === null || _d === void 0 ? void 0 : _d.call(runtimeHooks, el, location.pathname, framework, handler.PullDownRefresh) : el, pathname + stringify(handler.getQuery(stacksIndex)), {}, loadConfig);
1849
+ return handler.load(page, pageConfig, stacksIndex);
1735
1850
  }
1736
1851
  };
1737
1852
  if (history.location.pathname === '/') {
1738
- history.replace(prependBasename((config.entryPagePath || ((_a = routes[0].path) === null || _a === void 0 ? void 0 : _a[0])) + history.location.search));
1853
+ history.replace(prependBasename(entryPagePath + history.location.search));
1739
1854
  }
1740
1855
  render({ location: history.location, action: r.Push });
1741
- app.onShow(qs(stacks.length));
1856
+ app.onShow(handler.getQuery(stacks.length));
1742
1857
  return history.listen(render);
1743
1858
  }
1744
1859