@morjs/runtime-web
Version:
mor runtime for web
234 lines • 10.3 kB
JavaScript
;
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