UNPKG

@morjs/runtime-web

Version:
234 lines 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createRouter = exports.tigaRouterChangeHandler = exports.unloadPageByCondition = exports.batchUnloadPage = void 0; const tslib_1 = require("tslib"); const react_1 = tslib_1.__importDefault(require("react")); const react_dom_1 = tslib_1.__importDefault(require("react-dom")); const universal_router_1 = tslib_1.__importDefault(require("universal-router")); require("./api"); const dom_1 = require("./dom"); const history_1 = require("./history"); const pageStack_1 = require("./pageStack"); const tabbar_1 = require("./tabbar"); const types_1 = require("./types"); const url_1 = require("./url"); let routerAction; let rootElement; function initRouter(config) { var _a, _b, _c, _d, _e, _f, _g; const alias = ((_a = config.router) === null || _a === void 0 ? void 0 : _a.customRoutes) || {}; const routes = []; for (let i = 0; i < config.pages.length; i++) { const route = (_c = (_b = config.routes) === null || _b === void 0 ? void 0 : _b[i]) !== null && _c !== void 0 ? _c : {}; const path = (0, url_1.addLeadingSlash)(route === null || route === void 0 ? void 0 : route.path); if (i === 0) { routes.push({ path: '/', action: route.loader }); } if (alias[path] === '/') { console.error('定义路由不能是 /,必须带有路径,例/index'); } routes.push({ path: alias[path] || path, action: route.loader }); } const router = new universal_router_1.default(routes); function render(location, action) { router.resolve(location.pathname).then((component) => { location.hash = window.location.hash; routerAction = { location, action }; const element = component.default ? component.default : component; if (action === types_1.Action.PUSH) { hidePage((0, pageStack_1.getCurPage)()); loadPage(location, element); } else if (action === types_1.Action.REPLACE) { unloadPage((0, pageStack_1.getCurPage)()); pageStack_1.pageStack.pop(); loadPage(location, element); } else if (action === types_1.Action.POP) { tigaRouterChangeHandler({ detail: { location, action, delta: 1 } }, element); } }); } render(history_1.history.location, types_1.Action.PUSH); (_e = (_d = window.getApp()) === null || _d === void 0 ? void 0 : _d.onLaunch) === null || _e === void 0 ? void 0 : _e.call(_d, (0, url_1.getRelaunchOptions)()); (_g = (_f = window.getApp()) === null || _f === void 0 ? void 0 : _f.onShow) === null || _g === void 0 ? void 0 : _g.call(_f, (0, url_1.getRelaunchOptions)()); history_1.history.listen(render); } function setRootElement(element) { rootElement = element; } function getRootElement() { return rootElement ? rootElement : document === null || document === void 0 ? void 0 : document.getElementById('app'); } const pushPage = (page) => { const allPages = [...pageStack_1.pageStack]; // 移除页面中已经存在的此页面(先删除后直接将此页面推入顶栈即可) allPages.forEach((p, index) => page.pageId === p.pageId && pageStack_1.pageStack.splice(index, 1)); pageStack_1.pageStack.push(page); }; function loadPage(location, component) { var _a, _b; const pageId = (0, url_1.getPageId)(location); const pageEl = document.getElementById(pageId); if (pageEl) { const page = pageStack_1.pageStack.find((pageItem) => pageItem.pageId === pageId); pushPage(page); (_a = page === null || page === void 0 ? void 0 : page.onShow) === null || _a === void 0 ? void 0 : _a.call(page); pageEl.style.display = 'block'; } else { const tigaPage = document.createElement('div'); tigaPage.classList.add('tiga-page-wrap'); tigaPage.id = pageId; (_b = getRootElement()) === null || _b === void 0 ? void 0 : _b.append(tigaPage); const reactElement = react_1.default.isValidElement(component) ? component : react_1.default.createElement(component); react_dom_1.default.render(reactElement, document.getElementById(pageId)); } } function showPage(page) { if (page != null) { const pageEl = document.getElementById(page.pageId); if (pageEl) { // 适配api中的问题:eleme 容器中history.push后history栈没变化,加上setTimeout解决问题 setTimeout(() => { var _a; return (_a = page === null || page === void 0 ? void 0 : page.onShow) === null || _a === void 0 ? void 0 : _a.call(page); }); pageEl.style.display = 'block'; } } } function hidePage(page) { var _a; if (page != null) { const pageEl = document.getElementById(page.pageId); if (pageEl) { (_a = page.onHide) === null || _a === void 0 ? void 0 : _a.call(page); pageEl.style.display = 'none'; } } } function unloadPage(page) { var _a; if (page != null) { const pageEl = document.getElementById(page.pageId); if (pageEl) { react_dom_1.default.unmountComponentAtNode(pageEl); (_a = pageEl === null || pageEl === void 0 ? void 0 : pageEl.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(pageEl); } } } const unLoadOrHidePage = (page) => { const existPage = pageStack_1.pageStack.find((item) => item.pageId === page.pageId); if (!existPage) { unloadPage(page); } else { hidePage(page); } }; // 批量卸载页面 function batchUnloadPage(delta) { const lastPageIndex = pageStack_1.pageStack.length - delta; const deletedPages = pageStack_1.pageStack.splice(lastPageIndex >= 0 ? lastPageIndex : 0, delta); deletedPages.forEach(unLoadOrHidePage); } exports.batchUnloadPage = batchUnloadPage; // 按照回调结果卸载页面 function unloadPageByCondition(callback) { const allPages = [...pageStack_1.pageStack]; allPages.forEach((page, index) => { const hitCondition = callback(page); if (hitCondition === true) { // 从路由栈中移除该页面 pageStack_1.pageStack.splice(index, 1); // 命中条件,说明该页面需要删除或者隐藏 unloadPage(page); } }); } exports.unloadPageByCondition = unloadPageByCondition; function pageCreateHandler(e) { const pageConfig = createPageConfig(e.detail); switch (routerAction.action) { case types_1.Action.PUSH: pageStack_1.pageStack.push(pageConfig); break; case types_1.Action.REPLACE: pageStack_1.pageStack.push(pageConfig); // eslint-disable-next-line no-fallthrough default: break; } } function createPageConfig(pageConfig) { const { location } = pageConfig; delete pageConfig.location; return Object.assign(Object.assign(Object.assign({}, pageConfig), (0, url_1.getPathAndOptions)(routerAction.location)), { pageId: (0, url_1.getPageId)(routerAction.location), __location: location }); } // history listener无法检测POP delta, 故在action:POP场景下,特殊处理 let popping = false; function tigaRouterChangeHandler(e, component) { const { action, delta } = e.detail || {}; if (action === 'POP' && delta && !popping) { popping = true; routerAction = e.detail; batchUnloadPage(routerAction.delta); const targetPageId = (0, url_1.getPageId)(routerAction.location); const targetPage = pageStack_1.pageStack.find((item) => item.pageId === targetPageId); if (targetPage) { showPage(targetPage); // 矫正 手动修改url后,pageStack偏差 if (targetPage.pageId !== (0, pageStack_1.getCurPage)().pageId) { pageStack_1.pageStack.push(targetPage); } } else { // 手动修改url, history action为POP, 需要特殊处理 routerAction.action = types_1.Action.PUSH; batchUnloadPage(1); loadPage(location, component); } setTimeout(() => { popping = false; }, 200); } } exports.tigaRouterChangeHandler = tigaRouterChangeHandler; function pageVisibilityChange() { var _a, _b, _c, _d, _e, _f, _g, _h; if (document.hidden) { (_b = (_a = window.getApp()) === null || _a === void 0 ? void 0 : _a.onHide) === null || _b === void 0 ? void 0 : _b.call(_a); (_d = (_c = (0, pageStack_1.getCurPage)()) === null || _c === void 0 ? void 0 : _c.onHide) === null || _d === void 0 ? void 0 : _d.call(_c); } else { (_f = (_e = window.getApp()) === null || _e === void 0 ? void 0 : _e.onShow) === null || _f === void 0 ? void 0 : _f.call(_e, (0, url_1.getRelaunchOptions)()); (_h = (_g = (0, pageStack_1.getCurPage)()) === null || _g === void 0 ? void 0 : _g.onShow) === null || _h === void 0 ? void 0 : _h.call(_g); } } function registerEventLister() { const routerChangeEvent = '__tigaRouterChange'; const pageCreateEvent = 'tigaPageCreate'; window.addEventListener(routerChangeEvent, tigaRouterChangeHandler, false); window.addEventListener(pageCreateEvent, pageCreateHandler, false); document.addEventListener('visibilitychange', pageVisibilityChange, false); } function createRouter(config, element) { const { router } = config; setRootElement(element); (0, url_1.setCustomRoutes)(router === null || router === void 0 ? void 0 : router.customRoutes); (0, url_1.setBaseName)(router === null || router === void 0 ? void 0 : router.baseName); (0, url_1.setPages)(config.pages); (0, history_1.setHistoryMode)(router === null || router === void 0 ? void 0 : router.mode, router === null || router === void 0 ? void 0 : router.baseName); (0, dom_1.initLayout)(element); (0, tabbar_1.initTabBar)(config); initRouter(config); registerEventLister(); } exports.createRouter = createRouter; //# sourceMappingURL=router.js.map