UNPKG

@bye_past/vue-keep

Version:

缓存你的页面组件, 使得可以比手机APP更好的体验效果

122 lines (104 loc) 3.59 kB
import { assign } from '../utils/index'; function resetComponentsName(router, isChildren) { const routerVersion = router.constructor.version?.replace(/\.(\d+)$/, '$1'); if (routerVersion < 3.5) { console.error('vue-keep: vue-router version is lower than 3.5.0, please upgrade vue-router'); return; } const routes = isChildren ? router : router.getRoutes(); routes.forEach(function(route) { if (!route?.components?.default) return; if (route.children?.length > 0) { resetComponentsName(route.children, true); }; if (typeof route.components.default === 'function') { const oldComponent = route.components.default; return (route.components.default = async() => { const newComponent = await oldComponent(); const { writable: isOnly } = Object.getOwnPropertyDescriptor(newComponent.default, 'name') || { writable: true }; // vue2 vue-property-decorator Component 装饰器 设置过的类组件无法设置只读属性 name newComponent.default._canCoveredName = isOnly; isOnly && (newComponent.default.name = route.name); if (isOnly && !route.name) { console.error('vue-keep: this component is not cached, did you forget to set the name in the route?'); } return newComponent; }); }; route.components.default.name = route.name; }); }; function getBaseOptions() { const extendList = ['push', 'replace', 'go', 'back', 'forward']; const obj = Object.create(null); return { extendList, obj }; } function addRoute(router) { const routerPrototype = router.constructor.prototype; let oldAddRoute = router.addRoute; if (routerPrototype.addRoute) { oldAddRoute = routerPrototype.addRoute; return (routerPrototype.addRoute = newAddRoute); } router.addRoute = newAddRoute; let waiting = false; function newAddRoute() { oldAddRoute.call(this, ...arguments); if (!waiting) { waiting = true; Promise.resolve().then(() => { resetComponentsName(router); }); } }; } let isJump; function jump(router, callback) { return function({ type = 'push' } = {}) { isJump = true; if (typeof arguments[0] === 'number') { const params = arguments[1]; if (typeof params !== 'object') return; type = params.type || 'go'; callback(type, assign({ delta: arguments[0] || 0 }, params)); router[params.type || 'go'].call(this, arguments[0] || 0); return (isJump = false); } callback(type, arguments[0]); router[type].call(this, ...arguments); isJump = false; }; } function router3x(router, callback) { const { extendList, obj } = getBaseOptions(); const historyPrototype = router.history.constructor.prototype; const routerPrototype = router.constructor.prototype; addRoute(router); routerPrototype.jump = jump(router, callback); extendList.forEach((key) => { obj[key] = historyPrototype[key] || (() => historyPrototype.go(1)); historyPrototype[key] = function() { isJump || callback(key, ...arguments); new Promise(resolve => resolve()) .then(() => obj[key].call(this, ...arguments)); }; }); return router; } function router4x(router, callback) { const { extendList, obj } = getBaseOptions(); addRoute(router); router.jump = jump(router, callback); extendList.forEach((key) => { obj[key] = router[key]; router[key] = function(to) { isJump || callback(key, ...arguments); return obj[key](to); }; }); } export { router3x, router4x, resetComponentsName };