界面、资源与生命周期
处理激活、停用、资源地址、样式与异步清理。
本页目录
一次打开的生命周期#
扫描清单 → 加载样式和有序脚本 → 注册定义
→ activate(api, host) → 用户操作
→ deactivate() → 回收自己的视图和业务资源宿主运行时公开了 register、load、activate、deactivate、disable、status 和 get。业务组件通常只需要注册定义,由宿主完成打开与装配,不必自行反复加载依赖。
activate 应该做什么#
- 验证挂载节点和必要接口。
- 创建组件自己的根节点、状态与事件。
- 读取打开当前视图真正需要的最少信息。
- 对初始化失败给出原因,而不是留下空白窗口。
初始化可以返回 Promise。不要在每次激活时插入重复脚本、覆盖公共全局变量,或扫描用户整个项目来“预热”。
deactivate 怎样清理#
| 资源 | 应保存什么 | 停用时处理 |
|---|---|---|
| DOM 事件 | 节点、事件名、函数引用 | 移除自己注册的监听 |
| 订阅 | 实际返回的取消函数 | 调用本次订阅的清理函数 |
| 计时器 | timer ID | clearTimeout / clearInterval |
| Observer | Observer 实例 | disconnect() |
| 编辑器、画布实例 | 组件实例 | 使用它自己的 dispose / destroy |
| 网络请求 | 支持取消的控制器 | 取消请求,并阻止旧回调写回 |
| 后台计算 | 真实任务或进程身份 | 调用受支持的停止机制 |
| 临时预览 | 自己生成的对象 URL | URL.revokeObjectURL() |
一个可以复用的清理容器#
下面是插件内部的组织工具,不是宿主 API。资源建立后立即登记清理,比到停用时再猜有哪些监听更可靠。
function createCleanup() {
const callbacks = [];
return {
add(dispose) {
if (typeof dispose === 'function') callbacks.push(dispose);
},
run() {
const errors = [];
while (callbacks.length) {
try { callbacks.pop()(); } catch (error) { errors.push(error); }
}
return errors;
}
};
}不要用 removeAllListeners 清空宿主或其他组件的订阅。部分旧事件接口会替换之前的回调,也不返回取消函数;必须逐个核对 preload 的真实实现。
界面、样式和可访问性#
根节点使用唯一类名;按钮声明 type="button",输入提供标签,进度或错误使用 role="status" 等可理解的反馈。长文件名可换行或截断,但应保留完整名称的查看方式。
窄窗口中把操作区放在能触达的位置,局部表格与代码块各自滚动。减少动态效果时停掉装饰动画,页面失焦或视口外不持续运行绘图循环。
本地资源与正式加密资源#
清单中的脚本和样式路径相对组件根目录。开发态可读的文件,在正式包中可能通过受支持的组件资源地址提供,不能硬编码开发机盘符、用户目录或假定 file:// 始终可用。
加密组件窗口的资源地址和授权准备由宿主负责。不要自己拼接解密地址、复用别的组件窗口的资源授权,或把密钥写进源码。
关闭、未保存状态与重新打开#
编辑工具应明确:哪些变化只在内存里,哪些已经保存。保存过程中又发生输入时,要保留较新内容的未保存状态;旧保存回调不能清掉新修改。
需要拦截关闭的组件,先核对目标版本支持的窗口关闭约定。不能只监听网页 unload 就承诺所有文件一定保存成功。关闭后再次打开的验收,应包括错误恢复和清理结果,而不只是界面出现。