在angular/angularjs混合应用程序中结合使用downgradeModule和downgradeInjectable会导致错误 [英] Using downgradeModule in conjunction with downgradeInjectable in an angular / angularjs hybrid application results in error

查看:114
本文介绍了在angular/angularjs混合应用程序中结合使用downgradeModule和downgradeInjectable会导致错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在angular 5.0中,升级模块现在可以选择使用downgradeModule,该模块在angular区域之外运行angularjs.在尝试这种方法时,我遇到了使用downgradeInjectable的问题.

With angular 5.0 the upgrade module now has the option of using downgradeModule which runs angularjs outside of the angular zone. While experimenting with this I have run into a problem with using downgradeInjectable.

我收到错误:

未捕获的错误:在引导Angular模块之前尝试获取Angular注射器.

在angular js中引导角度工作正常

import 'zone.js/dist/zone.js';
import * as angular from 'angular';
/**
 * Angular bootstrapping
 */
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { decorateModuleRef } from 'src/environment';
import { AppModule } from 'src/app/app.module';
import { downgradeModule } from '@angular/upgrade/static';

export const bootstrapFn = ( extraProviders ) => {
    const platformRef = platformBrowserDynamic( extraProviders );
    return platformRef
        .bootstrapModule( AppModule )
        .then( decorateModuleRef );
};

angular.module( 'app.bootstrap', [
    downgradeModule( bootstrapFn ),
] );

但是...

由于自举是在初始化angularjs之后进行的,所以我无法再进行降级的可注入工作.

Since the bootstrapping takes place after angularjs has been initialized I can no longer get the downgrade injectable working.

要降级的服务

import { Injectable, Inject, OnInit } from '@angular/core';

@Injectable()
export class MobileService implements OnInit{
    constructor(
        @Inject( 'angularjsDependency1' ) public angularjsDependency1 : any,
        @Inject( 'angularjsDependency2' ) public angularjsDependency2 : any,
    ) {}

}

降级可注射尝试

import * as angular from 'angular';
import { downgradeInjectable } from '@angular/upgrade/static';
import { MyService } from 'src/services/myService/myService';

export const myServiceDowngraded = angular.module( 'services.mobileService', [
    angularjsDependency1,
    angularjsDependency2,
] )

.factory(
    'mobileService',
    downgradeInjectable( MyService ),
).name;

当"downgradeInjectable(MyService)运行时,由于尚未引导角度,角度注入器尚不可用.因此,错误:

When "downgradeInjectable( MyService ) runs the angular injector is not available yet since angular hasn't been bootstrapped. Hence the error:

未捕获的错误:在引导Angular模块之前尝试获取Angular注射器.

有人知道我该如何解决吗?

Does anyone have an idea how I might fix this?

推荐答案

此线程中的答案帮助我找到了解决方案,但没有一个包含圣杯:

Answers in this thread helped me find a solution, but none contains the holy grail:

  1. 在应用程序的代码旁边创建service-boostrap组件是行不通的,因为与AngularJS不同,Angular是异步加载的.这给出了相同的错误Trying to get the Angular injector before bootstrapping an Angular module.
  2. 创建一个包裹了AngularJS代码的service-bootstrap组件,但后来我遇到了Angular构成者内部的更改检测问题,如
  1. Creating a service-boostrap component aside the app's code does not work, because Angular is loaded asynchronously, unlike AngularJS. This gives the same error Trying to get the Angular injector before bootstrapping an Angular module.
  2. Creating a service-bootstrap component wrapping the AngularJS code kind of worked, but then I experienced issues with change detection inside Angular composants, as described in this issue on github.
  3. In the github issue, someone suggested to edit @angular/upgrade source code to change a false to true to force components to be created in the Zone. But in this case it seems to cause performance issues (it seemed to launch ngZone's code multiple times on user events)
  4. In order for the app to work correctly, I needed :
  1. 不要让包含AngularJS的ng组件包含Angular组件.我们只需要包含Angular组件的AngularJS.
  2. 确保在名为service-bootstrap的第一个角度组件之后创建使用Angular服务的AngularJS组件.
  1. Not to have ng components containing AngularJS components containing Angular components. We need to only have AngularJS containing Angular components.
  2. Make sure that AngularJS components using Angular services are created after a first angular component, named service-bootstrap

为此,我创建了一个稍作修改的service-bootstrap组件:

To acheive this, I created a slightly modified service-bootstrap component:

import { Component, Output, EventEmitter, AfterViewInit } from "@angular/core";

@Component({
    selector: 'service-bootstrap',
    template: ``
})
export class ServiceBootstrapComponent implements AfterViewInit{
    @Output()
    public initialized: EventEmitter<void> = new EventEmitter();

    public ngAfterViewInit(){
        this.initialized.emit();
    }
}

在Angular模块中将此组件声明为entryComponent,并调用downgradeComponent在AngularJS中注册它:

Declared this component as entryComponent in the Angular module and called downgradeComponent to register it in AngularJS:

import { downgradeModule, downgradeInjectable, downgradeComponent } from '@angular/upgrade/static';

const bootstrapFn = (extraProviders: StaticProvider[]) => {
    const platformRef = platformBrowserDynamic(extraProviders);
    return platformRef.bootstrapModule(AppModule);
};

const downgradedModule = downgradeModule(bootstrapFn);

const app = angular.module('ngApp', [
    downgradedModule,
    'app'
]);

app.directive('serviceBootstrap', downgradeComponent({ component: ServiceBootstrapComponent }));

然后(魔术发生在这里),我创建了一个新的AngularJS组件:

Then (and the magic happens here), I created a new AngularJS component:

angular.module("app")
    .directive('ng1App', ng1AppDirective);

function ng1AppDirective(){
    return {
        template: `
            <service-bootstrap (initialized)="onInit()"></service-bootstrap>
            <section ng-if="initialized">
              <!-- Your previous app's code here -->
            </section>
        `,
        controller: ng1AppController,
        scope: {},
    };
}

ng1AppController.$inject = ['$scope'];
function ng1AppController($scope){
    $scope.onInit = onInit;
    $scope.initialized = false;

    function onInit(){
        $scope.initialized = true;
    }
}

然后,我的index.html仅引用了此组件

Then, my index.html only referenced this component

<body>
  <ng1-app></ng1-app>
</body>

通过这种方法,我没有将AngularJS组件嵌套在Angular组件内(这会破坏Angular组件中的更改检测),但我仍然确保在访问Angular提供程序之前先加载了第一个Angular组件.

With this approach, I'm not nesting AngularJS components inside Angular components (which breaks change detection in Angular components), and still I ensure that a first Angular component is loaded before accessing the Angular providers.

这篇关于在angular/angularjs混合应用程序中结合使用downgradeModule和downgradeInjectable会导致错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆