【问题标题】:How to make ng2-redux work with module lazy loading within an Angular 4 SPA?如何使 ng2-redux 在 Angular 4 SPA 中使用模块延迟加载?
【发布时间】:2017-11-08 03:38:53
【问题描述】:

我正在尝试在一个使用延迟加载 (loadChildren) 的小型 Angular 4 应用程序中引入 Redux,但我无法使其工作:

1)相关配置(package.json)

"@angular/common": "4.4.5",
"@angular/compiler": "4.4.5",
"@angular/compiler-cli": "4.4.5",
"@angular/core": "4.4.5",
"@angular/router": "4.4.5",
"@ngtools/webpack": "1.5.0",
"@types/webpack-env": "1.13.0",
"angular2-template-loader": "0.6.2",
"ng2-redux": "^5.1.2",
"redux": "^3.7.2",

2) app.module.ts

@NgModule({
    declarations: [
        AppComponent,
    ],
    imports: [
        BrowserAnimationsModule,
        CustomCoreModule,
        NgReduxModule,
        AdvancedModule,
        AppRoutingModule,
    ],
    providers: [

    ]
})

export class AppModuleShared {
    constructor(
        private ngRedux: NgRedux<IAppState>,
        private devTools: DevToolsExtension) {

        var enhancers = isDevMode() ? [devTools.enhancer()] : [];
        console.log("AppModuleShared configuring store", this.ngRedux);
        ngRedux.configureStore(rootReducer, INITIAL_STATE, [] /*, enhancers */);
    }
}

3) app-routing.module.ts(非工作)

export const routes: Routes = [
    { path: 'advanced', loadChildren: () => AdvancedModule }, 
    { path: '**', component: PageNotFoundComponent }
];

@NgModule({
    imports: [RouterModule.forRoot(routes, { enableTracing: true, preloadingStrategy: PreloadAllModules })],
    exports: [RouterModule]
})
export class AppRoutingModule { }

4) 高级模块.ts

@NgModule({
    imports: [CommonModule, SharedModule, TodosModule, MessagingModule, AdvancedRoutingModule],
    declarations: [AngularMaterialTestComponent, ReduxTestComponent, TableTestComponent],
    providers: []
})
export class AdvancedModule { }

5) 消息传递.module.ts

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [MessagesComponent],
  exports: [MessagesComponent]
})
export class MessagingModule { }

6)messages.component.ts

@Component({
    selector: 'app-messages',
    templateUrl: './messages.component.html',
    styleUrls: ['./messages.component.css']
})
export class MessagesComponent {
    @select((s: IAppState) => s.messaging.messaging.newMessages) newMessages: Observable<any>;

    constructor(private ngRedux: NgRedux<{}>) {
        console.log("MessagesComponent started", this.ngRedux);
    }

    increment() {
        this.ngRedux.dispatch({ type: INCREMENT });
    }

    decrement() {
        this.ngRedux.dispatch({ type: DECREMENT });
    }
}

当我尝试递增时,它会失败并出现以下错误:

派送失败:您是否忘记配置您的商店? https://github.com/angular-redux/ng2-redux/blob/master/README.md#quick-start

this.ngRedux 在这种情况下与app.module.ts 中的不同(例如 _store 是 null 而不是有值),所以很明显我没有收到正确的实例。

如果我更改app-routing.module.ts 中的advanced 路由以禁用延迟加载并直接加载组件,它可以工作(当然,这会破坏AdvancedModule 中配置的所有路由):

{ path: 'advanced', loadChildren: () => AdvancedModule, component: ReduxTestComponent }

我的感觉是像我一样执行存储配置为时过早,但我不知道何时以及如何执行延迟加载模块的初始化以从中受益。

问题:如何让 ng2-redux 在 Angular 4 SPA 中使用模块延迟加载?

【问题讨论】:

    标签: angular redux lazy-loading


    【解决方案1】:

    我曾经遇到过类似的问题。 Angular 仅在使用 @select 时抛出错误,但问题并不明显。

    将@select 替换为ngRedux.getState()


    您还应该在 messages.component.ts 中将 IAppState 作为 NgRedux 的接口而不是 {}

    为 messages.component.ts 试试这个代码:

    export class MessagesComponent implements OnDestroy {
        newMessages: any;
    
        constructor(private ngRedux: NgRedux<IAppState>) {
           this.storeUnsubscribe = ngRedux.subscribe(() => {
             this.newMessages = ngRedux.getState().messaging.messaging.newMessages;
           });
        }
    
        increment() {
            this.ngRedux.dispatch({ type: INCREMENT });
        }
    
        decrement() {
            this.ngRedux.dispatch({ type: DECREMENT });
        }
    
        ngOnDestroy() {
            // Unsubscribe on component destroy to prevent memory leaks
            this.storeUnsubscribe();
        }
    }
    

    如果以上没有解决问题:

    1. 确保只在 app.module.ts 中导入 NgReduxModule
    2. 在一个组件中,你只需要NgRedux——不要导入NgReduxModule
    3. 用 package.json 的其余部分更新您的问题并导入文件

    【讨论】:

    • 我会试一试并提供反馈。不幸的是,() =&gt; AdvancedModule 语法在尝试发布项目时也会失败(AOT 不支持这种语法,需要像字符串或组件这样的静态语法)。谢谢。
    • 将匿名函数替换为命名函数,对AOT更友好。
    • 有一个类似的问题,我想强调这是解决我的问题的原因:“1. 确保只在 app.module.ts 中导入 NgReduxModule”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    相关资源
    最近更新 更多