@tarojs/router 3.3.14 → 3.3.15

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.js CHANGED
@@ -56,9 +56,56 @@ function prependBasename(url) {
56
56
  if ( url === void 0 ) url = '';
57
57
 
58
58
  return basename.replace(/\/$/, '') + '/' + url.replace(/^\//, '');
59
- }
59
+ }
60
+ var hasBasename = function (path, prefix) { return new RegExp('^' + prefix + '(\\/|\\?|#|$)', 'i').test(path); };
61
+ var stripBasename = function (path, prefix) { return hasBasename(path, prefix) ? path.substr(prefix.length) : path; };
62
+
63
+ var Stacks = function Stacks() {
64
+ this.stacks = [];
65
+ this.backDelta = 0;
66
+ };
67
+
68
+ var prototypeAccessors = { delta: { configurable: true },length: { configurable: true },last: { configurable: true } };
69
+ prototypeAccessors.delta.set = function (delta) {
70
+ if (delta > 0) {
71
+ this.backDelta = delta;
72
+ }
73
+ else {
74
+ --this.backDelta;
75
+ }
76
+ };
77
+ prototypeAccessors.length.get = function () {
78
+ return this.stacks.length;
79
+ };
80
+ prototypeAccessors.last.get = function () {
81
+ return this.stacks[this.length - 1];
82
+ };
83
+ Stacks.prototype.get = function get () {
84
+ return this.stacks;
85
+ };
86
+ Stacks.prototype.getItem = function getItem (index) {
87
+ return this.stacks[index];
88
+ };
89
+ Stacks.prototype.getDelta = function getDelta (pathname) {
90
+ if (this.backDelta >= 1) {
91
+ return this.backDelta;
92
+ }
93
+ // NOTE: 此处为了修复浏览器后退多级页面,在大量重复路由状况下可能出现判断错误的情况 (增强判断能力只能考虑在 query 中新增参数来判断,暂时搁置)
94
+ var prevIndex = this.stacks.findIndex(function (r) { var _a; return ((_a = r.path) === null || _a === void 0 ? void 0 : _a.replace(/\?.*/g, '')) === pathname; });
95
+ return this.length - 1 - prevIndex;
96
+ };
97
+ Stacks.prototype.getPrevIndex = function getPrevIndex (pathname) {
98
+ return this.length - 1 - this.getDelta(pathname);
99
+ };
100
+ Stacks.prototype.pop = function pop () {
101
+ return this.stacks.pop();
102
+ };
103
+ Stacks.prototype.push = function push (page) {
104
+ return this.stacks.push(page);
105
+ };
60
106
 
61
- var stacks = [];
107
+ Object.defineProperties( Stacks.prototype, prototypeAccessors );
108
+ var stacks = new Stacks();
62
109
 
63
110
  var routesAlias = {};
64
111
  function setRoutesAlias(alias) {
@@ -70,25 +117,6 @@ function addLeadingSlash(path) {
70
117
  }
71
118
  return path.charAt(0) === '/' ? path : '/' + path;
72
119
  }
73
- // 解决navigateBack调用delta>1时,路由栈异常问题
74
- // 比如:A->B->C,navigateBack({delta: 2}),此时路由栈中还存在B页面
75
- // 原因:主要是由于一次性退出多层级页面时,此action只会执行一次,此处进行手动处理
76
- var historyBackDelta = 1;
77
- function setHistoryBackDelta(delta) {
78
- historyBackDelta = delta;
79
- }
80
- // eslint-disable-next-line @typescript-eslint/ban-types
81
- var throttle = function (fn, threshold) {
82
- var lastTime = 0;
83
- return function () {
84
- var now = Date.now();
85
- if (now - lastTime > threshold) {
86
- fn.apply(this, arguments);
87
- lastTime = now;
88
- }
89
- };
90
- };
91
- var stripBasename = function (path, basename) { return path.startsWith(basename) ? path.replace(basename, '') : path; };
92
120
  var isTabBar = function (config) {
93
121
  var _a, _b;
94
122
  var ref = config.router;
@@ -105,6 +133,7 @@ var isTabBar = function (config) {
105
133
  };
106
134
 
107
135
  function processNavigateUrl(option) {
136
+ var _a;
108
137
  var pathPieces = J(option.url);
109
138
  // 处理自定义路由
110
139
  Object.keys(routesAlias).forEach(function (key) {
@@ -112,6 +141,18 @@ function processNavigateUrl(option) {
112
141
  pathPieces.pathname = routesAlias[key];
113
142
  }
114
143
  });
144
+ // 处理相对路径
145
+ if ((_a = pathPieces === null || pathPieces === void 0 ? void 0 : pathPieces.pathname) === null || _a === void 0 ? void 0 : _a.includes('./')) {
146
+ var parts = exports.history.location.pathname.split('/');
147
+ parts.pop();
148
+ pathPieces.pathname.split('/').forEach(function (item) {
149
+ if (item === '.') {
150
+ return;
151
+ }
152
+ item === '..' ? parts.pop() : parts.push(item);
153
+ });
154
+ pathPieces.pathname = parts.join('/');
155
+ }
115
156
  // 处理 basename
116
157
  pathPieces.pathname = prependBasename(pathPieces.pathname);
117
158
  // hack fix history v5 bug: https://github.com/remix-run/history/issues/814
@@ -142,7 +183,7 @@ async function navigate(option, method) {
142
183
  }
143
184
  }
144
185
  else if (method === 'navigateBack') {
145
- setHistoryBackDelta(option.delta);
186
+ stacks.delta = option.delta;
146
187
  exports.history.go(-option.delta);
147
188
  }
148
189
  }
@@ -176,7 +217,7 @@ function reLaunch(option) {
176
217
  return redirectTo(option);
177
218
  }
178
219
  function getCurrentPages() {
179
- return stacks;
220
+ return stacks.get();
180
221
  }
181
222
 
182
223
  /**
@@ -822,6 +863,7 @@ var UniversalRouter = function () {
822
863
 
823
864
  UniversalRouter.pathToRegexp = pathToRegexp_1;
824
865
 
866
+ var Taro = require('@tarojs/taro-h5');
825
867
  function initTabbar(config) {
826
868
  if (config.tabBar == null) {
827
869
  return;
@@ -833,7 +875,6 @@ function initTabbar(config) {
833
875
  tabbar.conf.homePage = exports.history.location.pathname === '/' ? homePage : exports.history.location.pathname;
834
876
  var routerConfig = config.router;
835
877
  tabbar.conf.mode = routerConfig && routerConfig.mode ? routerConfig.mode : 'hash';
836
- tabbar.conf.custom = !!routerConfig.customRoutes;
837
878
  if (routerConfig.customRoutes) {
838
879
  tabbar.conf.custom = true;
839
880
  tabbar.conf.customRoutes = routerConfig.customRoutes;
@@ -848,6 +889,7 @@ function initTabbar(config) {
848
889
  var container = document.getElementById('container');
849
890
  // eslint-disable-next-line no-unused-expressions
850
891
  container === null || container === void 0 ? void 0 : container.appendChild(tabbar);
892
+ Taro.initTabBarApis(config);
851
893
  }
852
894
 
853
895
  var routerConfig = Object.create(null);
@@ -871,6 +913,58 @@ function init(config) {
871
913
  initTabbar(config);
872
914
  }
873
915
 
916
+ var pageScrollFn;
917
+ var pageDOM = window;
918
+ function bindPageScroll(page, config) {
919
+ pageDOM.removeEventListener('scroll', pageScrollFn);
920
+ pageDOM = getScrollContainer();
921
+ var distance = config.onReachBottomDistance || 50;
922
+ var isReachBottom = false;
923
+ pageScrollFn = function () {
924
+ page.onPageScroll && page.onPageScroll({
925
+ scrollTop: pageDOM instanceof Window ? window.scrollY : pageDOM.scrollTop
926
+ });
927
+ if (isReachBottom && getOffset() > distance) {
928
+ isReachBottom = false;
929
+ }
930
+ if (page.onReachBottom &&
931
+ !isReachBottom &&
932
+ getOffset() < distance) {
933
+ isReachBottom = true;
934
+ page.onReachBottom();
935
+ }
936
+ };
937
+ pageDOM.addEventListener('scroll', pageScrollFn, false);
938
+ }
939
+ window.addEventListener('DOMSubtreeModified', function (e) {
940
+ var _a;
941
+ // @ts-ignore
942
+ var className = (_a = e.target) === null || _a === void 0 ? void 0 : _a.className;
943
+ if (className && /taro-tabbar__/.test(className)) {
944
+ pageDOM.removeEventListener('scroll', pageScrollFn);
945
+ pageDOM = getScrollContainer();
946
+ pageDOM.addEventListener('scroll', pageScrollFn, false);
947
+ }
948
+ }, false);
949
+ function getScrollContainer() {
950
+ if (document.querySelector('.taro-tabbar__tabbar') === null) {
951
+ // 没设置tabbar
952
+ return window;
953
+ }
954
+ else {
955
+ // 有设置tabbar
956
+ return document.querySelector('.taro-tabbar__panel') || window;
957
+ }
958
+ }
959
+ function getOffset() {
960
+ if (pageDOM instanceof Window) {
961
+ return document.documentElement.scrollHeight - window.scrollY - window.innerHeight;
962
+ }
963
+ else {
964
+ return pageDOM.scrollHeight - pageDOM.scrollTop - pageDOM.clientHeight;
965
+ }
966
+ }
967
+
874
968
  function createCommonjsModule(fn, module) {
875
969
  return module = { exports: {} }, fn(module, module.exports), module.exports;
876
970
  }
@@ -1427,14 +1521,25 @@ var queryString_5 = queryString.stringifyUrl;
1427
1521
  var queryString_6 = queryString.pick;
1428
1522
  var queryString_7 = queryString.exclude;
1429
1523
 
1524
+ function getSearch() {
1525
+ var search = '?';
1526
+ if (routerConfig.router.mode === 'hash') {
1527
+ var idx = location.hash.indexOf('?');
1528
+ if (idx > -1) {
1529
+ search = location.hash.slice(idx);
1530
+ }
1531
+ }
1532
+ else {
1533
+ search = location.search;
1534
+ }
1535
+ return search.substr(1);
1536
+ }
1430
1537
  var qs = function (stamp) {
1431
1538
  if ( stamp === void 0 ) stamp = 0;
1432
1539
 
1433
- var search = routerConfig.router.mode === 'hash'
1434
- ? location.hash.slice(routerConfig.router.pathname.length + 1)
1435
- : location.search;
1540
+ var search = getSearch();
1436
1541
  var query = search
1437
- ? queryString.parse(search.substr(1))
1542
+ ? queryString.parse(search)
1438
1543
  : {};
1439
1544
  if (stamp) {
1440
1545
  query.stamp = stamp.toString();
@@ -1442,98 +1547,14 @@ var qs = function (stamp) {
1442
1547
  return query;
1443
1548
  };
1444
1549
 
1445
- var pageScrollFn;
1446
- var pageDOM = window;
1447
- function bindPageScroll(page, config) {
1448
- pageDOM.removeEventListener('scroll', pageScrollFn);
1449
- pageDOM = getScrollContainer();
1450
- var distance = config.onReachBottomDistance || 50;
1451
- var isReachBottom = false;
1452
- pageScrollFn = function () {
1453
- page.onPageScroll && page.onPageScroll({
1454
- scrollTop: pageDOM instanceof Window ? window.scrollY : pageDOM.scrollTop
1455
- });
1456
- if (isReachBottom && getOffset() > distance) {
1457
- isReachBottom = false;
1458
- }
1459
- if (page.onReachBottom &&
1460
- !isReachBottom &&
1461
- getOffset() < distance) {
1462
- isReachBottom = true;
1463
- page.onReachBottom();
1464
- }
1465
- };
1466
- pageDOM.addEventListener('scroll', pageScrollFn, false);
1467
- }
1468
- window.addEventListener('DOMSubtreeModified', function (e) {
1469
- var _a;
1470
- // @ts-ignore
1471
- var className = (_a = e.target) === null || _a === void 0 ? void 0 : _a.className;
1472
- if (className && /taro-tabbar__/.test(className)) {
1473
- pageDOM.removeEventListener('scroll', pageScrollFn);
1474
- pageDOM = getScrollContainer();
1475
- pageDOM.addEventListener('scroll', pageScrollFn, false);
1476
- }
1477
- }, false);
1478
- function getScrollContainer() {
1479
- if (document.querySelector('.taro-tabbar__tabbar') === null) {
1480
- // 没设置tabbar
1481
- return window;
1482
- }
1483
- else {
1484
- // 有设置tabbar
1485
- return document.querySelector('.taro-tabbar__panel') || window;
1486
- }
1487
- }
1488
- function getOffset() {
1489
- if (pageDOM instanceof Window) {
1490
- return document.documentElement.scrollHeight - window.scrollY - window.innerHeight;
1491
- }
1492
- else {
1493
- return pageDOM.scrollHeight - pageDOM.scrollTop - pageDOM.clientHeight;
1494
- }
1495
- }
1496
-
1497
1550
  /* eslint-disable dot-notation */
1498
- function hidePage(page) {
1499
- if (page != null) {
1500
- page.onHide();
1501
- var pageEl = document.getElementById(page.path);
1502
- if (pageEl) {
1503
- pageEl.style.display = 'none';
1504
- }
1505
- }
1506
- }
1507
- function showPage(page, pageConfig, stacksIndex) {
1508
- if ( stacksIndex === void 0 ) stacksIndex = 0;
1509
-
1510
- if (page != null) {
1511
- page.onShow();
1512
- var pageEl = document.getElementById(page.path);
1513
- if (pageEl) {
1514
- pageEl.style.display = 'block';
1515
- }
1516
- else {
1517
- page.onLoad(qs(stacksIndex));
1518
- pageEl = document.getElementById(page.path);
1519
- pageOnReady(pageEl, page, false);
1520
- }
1521
- bindPageScroll(page, pageConfig || {});
1522
- }
1523
- }
1524
- function unloadPage(page) {
1525
- if (page != null) {
1526
- stacks.pop();
1527
- page.onUnload();
1528
- }
1529
- }
1530
- function pageOnReady(pageEl, page, onLoad) {
1551
+ function pageOnReady(page, onLoad) {
1531
1552
  if ( onLoad === void 0 ) onLoad = true;
1532
1553
 
1533
1554
  var _a;
1555
+ var pageEl = document.getElementById(page.path);
1534
1556
  if (pageEl && !(pageEl === null || pageEl === void 0 ? void 0 : pageEl['__isReady'])) {
1535
1557
  var el = pageEl.firstElementChild;
1536
- // eslint-disable-next-line no-unused-expressions
1537
1558
  (_a = el === null || el === void 0 ? void 0 : el['componentOnReady']) === null || _a === void 0 ? void 0 : _a.call(el).then(function () {
1538
1559
  runtime.requestAnimationFrame(function () {
1539
1560
  page.onReady();
@@ -1544,24 +1565,64 @@ function pageOnReady(pageEl, page, onLoad) {
1544
1565
  }
1545
1566
  }
1546
1567
  function loadPage(page, pageConfig, stacksIndex) {
1568
+ if ( pageConfig === void 0 ) pageConfig = {};
1547
1569
  if ( stacksIndex === void 0 ) stacksIndex = 0;
1548
1570
 
1549
- if (page !== null) {
1550
- var pageEl = document.getElementById(page.path);
1551
- if (pageEl) {
1552
- pageEl.style.display = 'block';
1553
- }
1554
- else {
1555
- page.onLoad(qs(stacksIndex), function () {
1556
- pageEl = document.getElementById(page.path);
1557
- pageOnReady(pageEl, page);
1558
- });
1559
- }
1560
- stacks.push(page);
1561
- page.onShow();
1562
- bindPageScroll(page, pageConfig || {});
1571
+ if (!page)
1572
+ { return; }
1573
+ var pageEl = document.getElementById(page.path);
1574
+ if (pageEl) {
1575
+ pageEl.style.display = 'block';
1563
1576
  }
1577
+ else {
1578
+ page.onLoad(qs(stacksIndex), function () { return pageOnReady(page, true); });
1579
+ }
1580
+ stacks.push(page);
1581
+ page.onShow();
1582
+ bindPageScroll(page, pageConfig);
1583
+ }
1584
+ function unloadPage(page, delta) {
1585
+ if ( delta === void 0 ) delta = 1;
1586
+
1587
+ if (!page)
1588
+ { return; }
1589
+ stacks.delta = --delta;
1590
+ stacks.pop();
1591
+ page.onUnload();
1592
+ if (delta >= 1)
1593
+ { unloadPage(stacks.last, delta); }
1564
1594
  }
1595
+ function showPage(page, pageConfig, stacksIndex) {
1596
+ if ( pageConfig === void 0 ) pageConfig = {};
1597
+ if ( stacksIndex === void 0 ) stacksIndex = 0;
1598
+
1599
+ if (!page)
1600
+ { return; }
1601
+ page.onShow();
1602
+ var pageEl = document.getElementById(page.path);
1603
+ if (pageEl) {
1604
+ pageEl.style.display = 'block';
1605
+ }
1606
+ else {
1607
+ page.onLoad(qs(stacksIndex), function () { return pageOnReady(page, false); });
1608
+ }
1609
+ bindPageScroll(page, pageConfig);
1610
+ }
1611
+ function hidePage(page) {
1612
+ if (!page)
1613
+ { return; }
1614
+ // NOTE: 修复多页并发问题,此处可能因为路由跳转过快,执行时页面可能还没有创建成功
1615
+ var pageEl = document.getElementById(page.path);
1616
+ if (pageEl) {
1617
+ pageEl.style.display = 'none';
1618
+ page.onHide();
1619
+ }
1620
+ else {
1621
+ setTimeout(function () { return hidePage(page); }, 0);
1622
+ }
1623
+ }
1624
+
1625
+ /* eslint-disable dot-notation */
1565
1626
  function createRouter(app, config, framework) {
1566
1627
  var _a;
1567
1628
  init(config);
@@ -1580,7 +1641,7 @@ function createRouter(app, config, framework) {
1580
1641
  var basename = config.router.basename;
1581
1642
  var router = new UniversalRouter(routes, { baseUrl: basename || '' });
1582
1643
  app.onLaunch();
1583
- var render = throttle(async function (ref) {
1644
+ var render = async function (ref) {
1584
1645
  var location = ref.location;
1585
1646
  var action = ref.action;
1586
1647
 
@@ -1616,65 +1677,49 @@ function createRouter(app, config, framework) {
1616
1677
  document.title = (_b = pageConfig.navigationBarTitleText) !== null && _b !== void 0 ? _b : document.title;
1617
1678
  enablePullDownRefresh = pageConfig.enablePullDownRefresh;
1618
1679
  }
1680
+ var currentPage = runtime.Current.page;
1681
+ var pathname = location.pathname;
1619
1682
  var shouldLoad = false;
1620
1683
  if (action === 'POP') {
1621
- unloadPage(runtime.Current.page);
1622
- var delta = historyBackDelta;
1623
- while (delta-- > 1) {
1624
- unloadPage(stacks.slice(-1)[0]);
1625
- }
1626
- // 最终必须重置为 1
1627
- setHistoryBackDelta(1);
1628
- var prevIndex = stacks.reduceRight(function (p, s, i) {
1629
- if (p !== 0)
1630
- { return p; }
1631
- else if (s.path === location.pathname + runtime.stringify(qs(i)))
1632
- { return i; }
1633
- else
1634
- { return 0; }
1635
- }, 0);
1636
- var prev = stacks[prevIndex];
1637
- if (prev) {
1638
- showPage(prev, pageConfig, prevIndex);
1684
+ // NOTE: 浏览器事件退后多次时,该事件只会被触发一次
1685
+ var prevIndex = stacks.getPrevIndex(pathname);
1686
+ var delta = stacks.getDelta(pathname);
1687
+ unloadPage(currentPage, delta);
1688
+ if (prevIndex > -1) {
1689
+ showPage(stacks.getItem(prevIndex), pageConfig, prevIndex);
1639
1690
  }
1640
1691
  else {
1641
1692
  shouldLoad = true;
1642
1693
  }
1643
1694
  }
1644
1695
  else if (action === 'PUSH') {
1645
- hidePage(runtime.Current.page);
1696
+ hidePage(currentPage);
1646
1697
  shouldLoad = true;
1647
1698
  }
1648
1699
  else if (action === 'REPLACE') {
1649
1700
  if (isTabBar(config)) {
1650
- hidePage(runtime.Current.page);
1651
- var pathname = stripBasename(config.router.pathname, basename);
1652
- var prevIndex$1 = stacks.findIndex(function (r) {
1653
- var _a;
1654
- return ((_a = r.path) === null || _a === void 0 ? void 0 : _a.replace(/\?.*/g, '')) === pathname;
1655
- });
1701
+ hidePage(currentPage);
1702
+ var prevIndex$1 = stacks.getPrevIndex(pathname);
1656
1703
  if (prevIndex$1 > -1) {
1657
- // tabbar 页且之前出现过,直接复用
1658
- var prev$1 = stacks[prevIndex$1];
1659
- return showPage(prev$1, pageConfig, prevIndex$1);
1704
+ // NOTE: tabbar 页且之前出现过,直接复用
1705
+ return showPage(stacks.getItem(prevIndex$1), pageConfig, prevIndex$1);
1660
1706
  }
1661
1707
  }
1662
1708
  else {
1663
- unloadPage(runtime.Current.page);
1709
+ unloadPage(currentPage);
1664
1710
  }
1665
1711
  shouldLoad = true;
1666
1712
  }
1667
1713
  if (shouldLoad) {
1668
1714
  var el = (_c = element.default) !== null && _c !== void 0 ? _c : element;
1669
1715
  var loadConfig = Object.assign({}, pageConfig);
1716
+ var stacksIndex = stacks.length;
1670
1717
  delete loadConfig['path'];
1671
1718
  delete loadConfig['load'];
1672
- var pathname$1 = stripBasename(config.router.pathname, basename);
1673
- var routerIndex = stacks.length;
1674
- var page = runtime.createPageConfig(enablePullDownRefresh ? (_d = runtimeHooks.createPullDownComponent) === null || _d === void 0 ? void 0 : _d.call(runtimeHooks, el, location.pathname, framework, routerConfig.PullDownRefresh) : el, pathname$1 + runtime.stringify(qs(routerIndex)), {}, loadConfig);
1675
- loadPage(page, pageConfig, routerIndex);
1719
+ var page = runtime.createPageConfig(enablePullDownRefresh ? (_d = runtimeHooks.createPullDownComponent) === null || _d === void 0 ? void 0 : _d.call(runtimeHooks, el, location.pathname, framework, routerConfig.PullDownRefresh) : el, pathname + runtime.stringify(qs(stacksIndex)), {}, loadConfig);
1720
+ return loadPage(page, pageConfig, stacksIndex);
1676
1721
  }
1677
- }, 500);
1722
+ };
1678
1723
  if (exports.history.location.pathname === '/') {
1679
1724
  exports.history.replace(prependBasename(routes[0].path + exports.history.location.search));
1680
1725
  }