4a76561a85
- 将时区列表提取到独立常量文件 `timezone.js` 中,便于维护和扩展 - 重构时间戳显示逻辑,将初始化功能从事件处理器中分离 - 引入 timerManager、eventManager 和 scriptManager 进行资源统一管理 - 更新 DOM 操作方式,使用 window.eventManager 替代直接 addEventListener - 改进时间戳更新函数,支持传入元素引用以提高灵活性 - 在路由加载脚本时增加调试日志,方便追踪组件加载过程 - 移除冗余的 DOM 工具函数(如 getElementById),统一使用原生方法 - 修复计时器清理问题,确保通过 timerManager 正确清除定时任务 - 初始化时间戳和日期输入框默认值,提升用户体验
116 lines
2.8 KiB
JavaScript
116 lines
2.8 KiB
JavaScript
export class ScriptManager {
|
|
constructor() {
|
|
this.currentScriptEl = null;
|
|
this.currentModule = null;
|
|
this.currentName = null;
|
|
}
|
|
|
|
async loadScript({ path, name, isModule = false, deps = [] }) {
|
|
console.log('loadScript');
|
|
console.log({ path, name, isModule, deps })
|
|
await this.unloadScript();
|
|
|
|
for (const dep of deps) {
|
|
await this._appendScript({ path: dep, isModule: false });
|
|
}
|
|
|
|
if (isModule) {
|
|
const absPath = (path = '?t' + Date.now());
|
|
this.currentModule = await import(absPath);
|
|
this.currentScriptEl = null;
|
|
this.currentName = name;
|
|
return this.currentModule;
|
|
} else {
|
|
await this._appendScript({ path, isModule: false });
|
|
this.currentName = name;
|
|
return window[name] || null;
|
|
}
|
|
}
|
|
|
|
async _appendScript({ path, isModule }) {
|
|
const s = document.createElement('script');
|
|
try {
|
|
s.src = path + '?t=' + Date.now();
|
|
s.type = isModule ? 'module' : 'text/javascript';
|
|
s.async = false;
|
|
s.onload = () => {
|
|
this.currentScriptEl = s;
|
|
};
|
|
} catch (e) {
|
|
throw new Error(`Failed to load script: ${path}`);
|
|
} finally {
|
|
document.body.appendChild(s);
|
|
}
|
|
}
|
|
|
|
async unloadScript() {
|
|
console.log('unloadScript');
|
|
try {
|
|
if (this.currentName && window[this.currentName]) {
|
|
const mod = window[this.currentName];
|
|
const unName = this._findUnmountName(mod);
|
|
if (unName && typeof mod[unName] === 'function') {
|
|
await mod[unName]();
|
|
}
|
|
}
|
|
|
|
if (this.currentModule) {
|
|
const mod = this.currentModule;
|
|
const unName = this._findUnmountName(mod);
|
|
if (unName && typeof mod[unName] === 'function') {
|
|
await mod[unName]();
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
|
|
if (this.currentScriptEl) {
|
|
try {
|
|
this.currentScriptEl.remove();
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
this.currentModule = null;
|
|
this.currentName = null;
|
|
}
|
|
|
|
_findInitName(obj) {
|
|
if (!obj) return null;
|
|
const candidates = ['init', 'start', 'main'];
|
|
for (const c of candidates) {
|
|
if (typeof obj[c] === 'function') {
|
|
return c;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
_findUnmountName(obj) {
|
|
if (!obj) return null;
|
|
const candidates = ['unmount', 'stop', 'destroy'];
|
|
for (const c of candidates) {
|
|
if (typeof obj[c] === 'function') {
|
|
return c;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
async runInit(name) {
|
|
if (this.currentModule) {
|
|
const mod = this.currentModule;
|
|
const init = this._findInitName(mod);
|
|
if (init) return mod[init]();
|
|
return null;
|
|
} else if (name && window[name]) {
|
|
const mod = window[name];
|
|
const init = this._findInitName(mod);
|
|
if (init) return mod[init]();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|