在Angular应用中嵌入AngularJS组件报错:AngularJS注入器未设置
嘿,我刚好在Angular升级项目里踩过这个坑,咱们来拆解一下这个报错的根源和解决办法:
错误到底是什么原因?
这个报错的核心就是你的Angular代码抢在AngularJS的注入器(injector)初始化完成前,就试图去访问它了。
按照升级指南的步骤,你应该已经引入了UpgradeModule,但大概率是初始化顺序出了问题——比如你可能在Angular的AppModule里过早注入了依赖AngularJS的服务,或者在Angular组件的构造函数里直接调用了AngularJS的服务,这时候AngularJS的injector还没被UpgradeModule完全初始化好,自然就会报错。
具体怎么解决?
1. 先把AppModule的启动顺序改对
确保你正确使用UpgradeModule,别在bootstrap数组里同时塞Angular组件和AngularJS模块,而是用ngDoBootstrap手动启动AngularJS,这样能保证Angular的基础环境先搭好,再初始化AngularJS的injector:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static'; import { AppComponent } from './app.component'; // 引入你的AngularJS模块 import { angularJSModule } from './angularjs-module'; @NgModule({ imports: [ BrowserModule, UpgradeModule ], declarations: [ AppComponent ], providers: [], bootstrap: [AppComponent] // 只bootstrap Angular的根组件 }) export class AppModule { constructor(private upgrade: UpgradeModule) {} ngDoBootstrap() { // 在这里手动启动AngularJS模块,确保顺序正确 this.upgrade.bootstrap(document.body, [angularJSModule.name], { strictDi: true }); } }
2. 别在构造函数里直接碰AngularJS服务
如果你需要在Angular里用AngularJS的服务,别直接在组件构造函数里注入,搞个桥接服务封装一下,然后在组件的生命周期钩子(比如ngOnInit)里再调用——因为这时候AngularJS的injector已经初始化完成了:
先写个桥接服务:
import { Injectable, Inject } from '@angular/core'; import { $injector } from '@angular/upgrade/static'; @Injectable({ providedIn: 'root' }) export class AngularJSBridgeService { private angularJSInjector: any; constructor(@Inject($injector) private injector: any) { this.angularJSInjector = injector.get('$injector'); } getAngularJSService(serviceName: string) { return this.angularJSInjector.get(serviceName); } }
然后在组件里这么用:
import { Component, OnInit } from '@angular/core'; import { AngularJSBridgeService } from './angularjs-bridge.service'; @Component({ selector: 'app-root', template: `<h1>Angular App</h1> <angularjs-component></angularjs-component>` }) export class AppComponent implements OnInit { constructor(private bridgeService: AngularJSBridgeService) {} ngOnInit() { // 到这个阶段,AngularJS的injector已经准备好啦 const myAngularJSService = this.bridgeService.getAngularJSService('myAngularJSService'); myAngularJSService.doSomething(); } }
3. 检查有没有提前跑的代码
比如你在模块级别写了console.log或者直接调用AngularJS服务的代码,这些代码会在AngularJS初始化前就执行,肯定会报错。把所有依赖AngularJS的逻辑都移到Angular的生命周期钩子或者AngularJS初始化完成之后再执行。
最后总结一下
这个问题本质就是初始化顺序没搞对——AngularJS的injector必须在Angular尝试访问它之前,被UpgradeModule初始化完成。调整一下AppModule的启动方式,用生命周期钩子延迟访问AngularJS服务,这个报错就搞定啦。
内容的提问来源于stack exchange,提问作者Nathan Friend

