1 | import { getHomePage, getCurrentPage, addLeadingSlash, stripBasename, stripTrailing, requestAnimationFrame, eventCenter, Current } from '@tarojs/runtime';
|
2 | import queryString from 'query-string';
|
3 | import { bindPageResize } from '../events/resize.js';
|
4 | import { bindPageScroll } from '../events/scroll.js';
|
5 | import { setHistory, history } from '../history.js';
|
6 | import { loadAnimateStyle, loadRouterStyle } from '../style.js';
|
7 | import { routesAlias } from '../utils/index.js';
|
8 | import NavigationBarHandler from './navigation-bar.js';
|
9 | import stacks from './stack.js';
|
10 |
|
11 |
|
12 | class PageHandler {
|
13 | constructor(config, history) {
|
14 | this.history = history;
|
15 | this.defaultAnimation = { duration: 300, delay: 50 };
|
16 | this.config = config;
|
17 | this.homePage = getHomePage(this.routes[0].path, this.basename, this.customRoutes, this.config.entryPagePath);
|
18 | this.originHomePage = this.config.entryPagePath || this.routes[0].path || this.basename;
|
19 | this.mount();
|
20 | this.navigationBarHandler = new NavigationBarHandler(this);
|
21 | }
|
22 | get currentPage() {
|
23 | const routePath = getCurrentPage(this.routerMode, this.basename);
|
24 | return routePath === '/' ? this.homePage : routePath;
|
25 | }
|
26 | get appId() { return this.config.appId || 'app'; }
|
27 | get router() { return this.config.router || {}; }
|
28 | get routerMode() { return this.router.mode || 'hash'; }
|
29 | get customRoutes() { return this.router.customRoutes || {}; }
|
30 | get routes() { return this.config.routes || []; }
|
31 | get tabBarList() { var _a; return ((_a = this.config.tabBar) === null || _a === void 0 ? void 0 : _a.list) || []; }
|
32 | get PullDownRefresh() { return this.config.PullDownRefresh; }
|
33 | 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; }
|
34 | get animationDelay() {
|
35 | var _a;
|
36 | return (typeof this.animation === 'object'
|
37 | ? this.animation.delay
|
38 | : this.animation
|
39 | ? (_a = this.defaultAnimation) === null || _a === void 0 ? void 0 : _a.delay
|
40 | : 0) || 0;
|
41 | }
|
42 | get animationDuration() {
|
43 | var _a;
|
44 | return (typeof this.animation === 'object'
|
45 | ? this.animation.duration
|
46 | : this.animation
|
47 | ? (_a = this.defaultAnimation) === null || _a === void 0 ? void 0 : _a.duration
|
48 | : 0) || 0;
|
49 | }
|
50 | set pathname(p) { this.router.pathname = p; }
|
51 | get pathname() { return this.router.pathname; }
|
52 |
|
53 | get originPathname() { return routesAlias.getOrigin(addLeadingSlash(stripBasename(this.pathname, this.basename))); }
|
54 | get basename() { return this.router.basename || ''; }
|
55 | get pageConfig() {
|
56 | const homePage = addLeadingSlash(this.homePage);
|
57 | return this.routes.find(r => {
|
58 | const pagePath = addLeadingSlash(r.path);
|
59 | return [pagePath, homePage].includes(this.originPathname);
|
60 | });
|
61 | }
|
62 | isTabBar(pathname) {
|
63 | var _a;
|
64 | const routePath = addLeadingSlash(stripBasename(pathname, this.basename)).split('?')[0];
|
65 | const pagePath = ((_a = Object.entries(this.customRoutes).find(([, target]) => {
|
66 | if (typeof target === 'string') {
|
67 | return target === routePath;
|
68 | }
|
69 | else if ((target === null || target === void 0 ? void 0 : target.length) > 0) {
|
70 | return target.includes(routePath);
|
71 | }
|
72 | return false;
|
73 | })) === null || _a === void 0 ? void 0 : _a[0]) || routePath;
|
74 | return !!pagePath && this.tabBarList.some(t => stripTrailing(t.pagePath) === pagePath);
|
75 | }
|
76 | isDefaultNavigationStyle() {
|
77 | var _a, _b;
|
78 | let style = (_a = this.config.window) === null || _a === void 0 ? void 0 : _a.navigationStyle;
|
79 | if (typeof ((_b = this.pageConfig) === null || _b === void 0 ? void 0 : _b.navigationStyle) === 'string') {
|
80 | style = this.pageConfig.navigationStyle;
|
81 | }
|
82 | return style !== 'custom';
|
83 | }
|
84 | isSamePage(page) {
|
85 | const routePath = stripBasename(this.pathname, this.basename);
|
86 | const pagePath = stripBasename(page === null || page === void 0 ? void 0 : page.path, this.basename);
|
87 | return pagePath.startsWith(routePath + '?');
|
88 | }
|
89 | get search() {
|
90 | let search = '?';
|
91 | if (this.routerMode === 'hash') {
|
92 | const idx = location.hash.indexOf('?');
|
93 | if (idx > -1) {
|
94 | search = location.hash.slice(idx);
|
95 | }
|
96 | }
|
97 | else {
|
98 | search = location.search;
|
99 | }
|
100 | return search.substring(1);
|
101 | }
|
102 | get usingWindowScroll() {
|
103 | var _a;
|
104 | let usingWindowScroll = false;
|
105 | if (typeof ((_a = this.pageConfig) === null || _a === void 0 ? void 0 : _a.usingWindowScroll) === 'boolean') {
|
106 | usingWindowScroll = this.pageConfig.usingWindowScroll;
|
107 | }
|
108 | const win = window;
|
109 | win.__taroAppConfig || (win.__taroAppConfig = {});
|
110 | win.__taroAppConfig.usingWindowScroll = usingWindowScroll;
|
111 | return usingWindowScroll;
|
112 | }
|
113 | getQuery(stamp = '', search = '', options = {}) {
|
114 | search = search ? `${search}&${this.search}` : this.search;
|
115 | const query = search
|
116 | ? queryString.parse(search, { decode: false })
|
117 | : {};
|
118 | query.stamp = stamp;
|
119 | return Object.assign(Object.assign({}, query), options);
|
120 | }
|
121 | mount() {
|
122 | setHistory(this.history, this.basename);
|
123 | this.pathname = history.location.pathname;
|
124 |
|
125 | this.animation && loadAnimateStyle(this.animationDuration);
|
126 | loadRouterStyle(this.tabBarList.length > 1, this.usingWindowScroll, this.router.enhanceAnimation);
|
127 | }
|
128 | onReady(page, onLoad = true) {
|
129 | var _a;
|
130 | const pageEl = this.getPageContainer(page);
|
131 | if (pageEl && !(pageEl === null || pageEl === void 0 ? void 0 : pageEl['__isReady'])) {
|
132 | const el = pageEl.firstElementChild;
|
133 | const componentOnReady = el === null || el === void 0 ? void 0 : el['componentOnReady'];
|
134 | if (componentOnReady) {
|
135 | componentOnReady === null || componentOnReady === void 0 ? void 0 : componentOnReady().then(() => {
|
136 | requestAnimationFrame(() => {
|
137 | var _a;
|
138 | (_a = page.onReady) === null || _a === void 0 ? void 0 : _a.call(page);
|
139 | pageEl['__isReady'] = true;
|
140 | });
|
141 | });
|
142 | }
|
143 | else {
|
144 | (_a = page.onReady) === null || _a === void 0 ? void 0 : _a.call(page);
|
145 | pageEl['__isReady'] = true;
|
146 | }
|
147 | onLoad && (pageEl['__page'] = page);
|
148 | }
|
149 | }
|
150 | load(page, pageConfig = {}, stampId, pageNo = 0) {
|
151 | var _a, _b;
|
152 | if (!page)
|
153 | return;
|
154 |
|
155 | stacks.push(page);
|
156 | const param = this.getQuery(stampId, '', page.options);
|
157 | let pageEl = this.getPageContainer(page);
|
158 | if (pageEl) {
|
159 | pageEl.classList.remove('taro_page_shade');
|
160 | this.isTabBar(this.pathname) && pageEl.classList.add('taro_tabbar_page');
|
161 | this.isDefaultNavigationStyle() && pageEl.classList.add('taro_navigation_page');
|
162 | this.addAnimation(pageEl, pageNo === 0);
|
163 | (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
|
164 | this.navigationBarHandler.load();
|
165 | this.bindPageEvents(page, pageConfig);
|
166 | this.triggerRouterChange();
|
167 | }
|
168 | else {
|
169 |
|
170 | (_b = page.onLoad) === null || _b === void 0 ? void 0 : _b.call(page, param, () => {
|
171 | var _a;
|
172 | pageEl = this.getPageContainer(page);
|
173 | this.isTabBar(this.pathname) && (pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.add('taro_tabbar_page'));
|
174 | this.isDefaultNavigationStyle() && (pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.add('taro_navigation_page'));
|
175 | this.addAnimation(pageEl, pageNo === 0);
|
176 | (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
|
177 | this.navigationBarHandler.load();
|
178 | this.onReady(page, true);
|
179 | this.bindPageEvents(page, pageConfig);
|
180 | this.triggerRouterChange();
|
181 | });
|
182 | }
|
183 | }
|
184 | unload(page, delta = 1, top = false) {
|
185 | var _a, _b, _c;
|
186 | if (!page)
|
187 | return;
|
188 | stacks.delta = --delta;
|
189 | stacks.pop();
|
190 | if (this.animation && top) {
|
191 | if (this.unloadTimer) {
|
192 | clearTimeout(this.unloadTimer);
|
193 | (_b = (_a = this.lastUnloadPage) === null || _a === void 0 ? void 0 : _a.onUnload) === null || _b === void 0 ? void 0 : _b.call(_a);
|
194 | this.unloadTimer = null;
|
195 | }
|
196 | this.lastUnloadPage = page;
|
197 | const pageEl = this.getPageContainer(page);
|
198 | pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_stationed');
|
199 | pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_show');
|
200 | if (pageEl) {
|
201 | pageEl.style.zIndex = '1';
|
202 | }
|
203 | this.unloadTimer = setTimeout(() => {
|
204 | var _a, _b;
|
205 | this.unloadTimer = null;
|
206 | (_b = (_a = this.lastUnloadPage) === null || _a === void 0 ? void 0 : _a.onUnload) === null || _b === void 0 ? void 0 : _b.call(_a);
|
207 | eventCenter.trigger('__taroPageOnShowAfterDestroyed');
|
208 | }, this.animationDuration);
|
209 | }
|
210 | else {
|
211 | const pageEl = this.getPageContainer(page);
|
212 | pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_stationed');
|
213 | pageEl === null || pageEl === void 0 ? void 0 : pageEl.classList.remove('taro_page_show');
|
214 | (_c = page === null || page === void 0 ? void 0 : page.onUnload) === null || _c === void 0 ? void 0 : _c.call(page);
|
215 | setTimeout(() => {
|
216 | eventCenter.trigger('__taroPageOnShowAfterDestroyed');
|
217 | }, 0);
|
218 | }
|
219 | if (delta >= 1)
|
220 | this.unload(stacks.last, delta);
|
221 | }
|
222 | show(page, pageConfig = {}, pageNo = 0) {
|
223 | var _a, _b;
|
224 | if (!page)
|
225 | return;
|
226 | const param = this.getQuery(page['$taroParams']['stamp'], '', page.options);
|
227 | let pageEl = this.getPageContainer(page);
|
228 | if (pageEl) {
|
229 | pageEl.classList.remove('taro_page_shade');
|
230 | this.addAnimation(pageEl, pageNo === 0);
|
231 | (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
|
232 | this.navigationBarHandler.load();
|
233 | this.bindPageEvents(page, pageConfig);
|
234 | this.triggerRouterChange();
|
235 | }
|
236 | else {
|
237 | (_b = page.onLoad) === null || _b === void 0 ? void 0 : _b.call(page, param, () => {
|
238 | var _a;
|
239 | pageEl = this.getPageContainer(page);
|
240 | this.addAnimation(pageEl, pageNo === 0);
|
241 | (_a = page.onShow) === null || _a === void 0 ? void 0 : _a.call(page);
|
242 | this.navigationBarHandler.load();
|
243 | this.onReady(page, false);
|
244 | this.bindPageEvents(page, pageConfig);
|
245 | this.triggerRouterChange();
|
246 | });
|
247 | }
|
248 | }
|
249 | hide(page, animation = false) {
|
250 | var _a, _b, _c, _d, _e, _f, _g, _h;
|
251 | if (!page)
|
252 | return;
|
253 |
|
254 | const pageEl = this.getPageContainer(page);
|
255 | if (pageEl) {
|
256 | if (animation) {
|
257 | if (this.hideTimer) {
|
258 | clearTimeout(this.hideTimer);
|
259 | this.hideTimer = null;
|
260 | (_c = (_b = (_a = this.lastHidePage) === null || _a === void 0 ? void 0 : _a.classList) === null || _b === void 0 ? void 0 : _b.add) === null || _c === void 0 ? void 0 : _c.call(_b, 'taro_page_shade');
|
261 | }
|
262 | this.lastHidePage = pageEl;
|
263 | this.hideTimer = setTimeout(() => {
|
264 | this.hideTimer = null;
|
265 | pageEl.classList.add('taro_page_shade');
|
266 | }, this.animationDuration + this.animationDelay);
|
267 | (_d = page.onHide) === null || _d === void 0 ? void 0 : _d.call(page);
|
268 | }
|
269 | else {
|
270 | if (this.hideTimer) {
|
271 | clearTimeout(this.hideTimer);
|
272 | this.hideTimer = null;
|
273 | (_g = (_f = (_e = this.lastHidePage) === null || _e === void 0 ? void 0 : _e.classList) === null || _f === void 0 ? void 0 : _f.add) === null || _g === void 0 ? void 0 : _g.call(_f, 'taro_page_shade');
|
274 | }
|
275 | (_h = page.onHide) === null || _h === void 0 ? void 0 : _h.call(page);
|
276 | pageEl.classList.add('taro_page_shade');
|
277 | this.lastHidePage = pageEl;
|
278 | }
|
279 | }
|
280 | else {
|
281 | setTimeout(() => this.hide(page), 0);
|
282 | }
|
283 | }
|
284 | addAnimation(pageEl, first = false) {
|
285 | if (!pageEl)
|
286 | return;
|
287 | if (this.animation && !first) {
|
288 | setTimeout(() => {
|
289 | pageEl.classList.add('taro_page_show');
|
290 | setTimeout(() => {
|
291 | pageEl.classList.add('taro_page_stationed');
|
292 | }, this.animationDuration);
|
293 | }, this.animationDelay);
|
294 | }
|
295 | else {
|
296 | pageEl.classList.add('taro_page_show');
|
297 | pageEl.classList.add('taro_page_stationed');
|
298 | }
|
299 | }
|
300 | getPageContainer(page) {
|
301 | var _a;
|
302 | const path = page ? page === null || page === void 0 ? void 0 : page.path : (_a = Current.page) === null || _a === void 0 ? void 0 : _a.path;
|
303 | const id = path === null || path === void 0 ? void 0 : path.replace(/([^a-z0-9\u00a0-\uffff_-])/ig, '\\$1');
|
304 | if (page) {
|
305 | return document.querySelector(`.taro_page#${id}`);
|
306 | }
|
307 | const el = (id
|
308 | ? document.querySelector(`.taro_page#${id}`)
|
309 | : document.querySelector('.taro_page') ||
|
310 | document.querySelector('.taro_router'));
|
311 | return el;
|
312 | }
|
313 | getScrollingElement(page) {
|
314 | if (this.usingWindowScroll)
|
315 | return window;
|
316 | return this.getPageContainer(page) || window;
|
317 | }
|
318 | bindPageEvents(page, config = {}) {
|
319 | var _a;
|
320 | const scrollEl = this.getScrollingElement(page);
|
321 | const distance = config.onReachBottomDistance || ((_a = this.config.window) === null || _a === void 0 ? void 0 : _a.onReachBottomDistance) || 50;
|
322 | bindPageScroll(page, scrollEl, distance);
|
323 | bindPageResize(page);
|
324 | }
|
325 | triggerRouterChange() {
|
326 | |
327 |
|
328 |
|
329 |
|
330 | setTimeout(() => {
|
331 | eventCenter.trigger('__afterTaroRouterChange', {
|
332 | toLocation: {
|
333 | path: this.pathname
|
334 | }
|
335 | });
|
336 | }, 0);
|
337 | }
|
338 | }
|
339 |
|
340 | export { PageHandler as default };
|