AngularJS TypeScript项目中如何监听普通TS文件的方法/事件?
如何在AngularJS TypeScript项目中订阅/监听普通TypeScript文件中的事件/方法?
针对你遇到的这个问题,咱们可以用几种不依赖AngularJS依赖注入体系的方案,轻松让ribbonController感知到progressBar.ts里的加载完成状态,完全适配你那个纯TS文件的场景:
方案一:给progressBar.ts添加回调订阅机制
我们可以在纯TS文件里维护一个回调函数队列,当加载进度达到100%时,自动触发所有已订阅的回调。这种方式简单直接,不需要依赖任何框架API:
修改progressBar.ts:
// progressBar.ts let loadComplete = false; // 存储所有订阅加载完成事件的回调函数 const completionCallbacks: (() => void)[] = []; export function updateGlobalProgressBar(progress: number) { // 保留你原来的进度更新逻辑 // ... // 当进度达到100%时标记完成,并触发所有回调 if (progress >= 100 && !loadComplete) { loadComplete = true; completionCallbacks.forEach(callback => callback()); } } // 提供订阅方法,外部可以注册回调 export function onLoadingComplete(callback: () => void) { // 如果加载已经完成,直接触发回调(避免错过事件) if (loadComplete) { callback(); } else { completionCallbacks.push(callback); } } export function loadingComplete(): boolean { return loadComplete; }
在ribbonController中使用:
// ribbonController.ts import { onLoadingComplete } from './progressBar'; class RibbonController { constructor(private _scope: any) { // 订阅加载完成事件 onLoadingComplete(() => { // 因为回调是在AngularJS的 digest 循环外触发的,需要用$apply通知视图更新 this._scope.$apply(() => { this._scope.loaderHasLoaded = true; }); }); } }
方案二:使用浏览器原生的自定义事件
利用浏览器的EventTarget API,让progressBar.ts触发自定义事件,然后在控制器中监听这个事件,这种方式更符合浏览器的事件驱动模型:
修改progressBar.ts:
// progressBar.ts let loadComplete = false; // 创建一个事件目标对象,用来触发和监听自定义事件 export const progressBarEvents = new EventTarget(); export function updateGlobalProgressBar(progress: number) { // 保留你原来的进度更新逻辑 // ... if (progress >= 100 && !loadComplete) { loadComplete = true; // 触发名为"loadingComplete"的自定义事件 progressBarEvents.dispatchEvent(new CustomEvent('loadingComplete')); } } export function loadingComplete(): boolean { return loadComplete; }
在ribbonController中使用:
// ribbonController.ts import { progressBarEvents } from './progressBar'; class RibbonController { constructor(private _scope: any) { const handleLoadingComplete = () => { this._scope.$apply(() => { this._scope.loaderHasLoaded = true; }); // 如果只需要监听一次加载完成,可以移除事件监听 progressBarEvents.removeEventListener('loadingComplete', handleLoadingComplete); }; // 注册事件监听 progressBarEvents.addEventListener('loadingComplete', handleLoadingComplete); // 控制器销毁时移除监听,避免内存泄漏 this._scope.$on('$destroy', () => { progressBarEvents.removeEventListener('loadingComplete', handleLoadingComplete); }); } }
为什么你之前的循环方案不行?
- do-while循环:会直接阻塞JavaScript线程,导致页面完全卡死,浏览器无法处理任何用户交互或更新视图,绝对不能用这种方式。
- if语句:只会执行一次判断,如果当时加载还没完成,就再也不会重新检查状态了,自然捕捉不到后续的完成事件。
额外提示
不管用哪种方案,都要记得在控制器销毁时清理订阅(比如移除事件监听),避免内存泄漏。另外,因为纯TS文件的逻辑不在AngularJS的digest循环内,所以更新scope变量时需要用$apply来通知Angular更新视图。
内容的提问来源于stack exchange,提问作者onmyway
相关产品推荐
相关产品推荐

