懒功能模块架构迁移到NGRX:Angular 8 [英] Lazy Feature Modules architecture migration to NGRX: Angular 8

查看:65
本文介绍了懒功能模块架构迁移到NGRX:Angular 8的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,我目前正在一个实现了惰性功能模块体系结构的应用程序中工作. 在下面,您可以看到项目的结构.

Hey guys currently i am working in an application with Lazy features modules architecture implemented. Below you can see how the project is structured.

由于应用程序不断增长,我们决定将其迁移到Ngrx.

Since the application is keep on growing we decided to migrate it to Ngrx.

对我来说,这是一种新模式,我正在寻找迁移指南,但是从头开始创建项目时我只能找到ngrx指南.

As is a new pattern for me i am searching for migration guidelines but i can only find ngrx guidelines when creating a project from scratch.

能否请您给我一些提示,指南,我应该在哪里小心以及可能的一些步骤摘要?

Could you please give me some hints, guidelines,where should i be careful , and possibly some steps summary?

谢谢.

推荐答案

准则

可以延迟加载您的商店,但这给我带来的问题多于收益.例如,基于路由器URL和混合了两个功能存储的已加载项目实体来获取选定的项目.以下文章为我提供了一种很好的分割存储的方法,同时允许应用程序的任何部分访问存储数据:

It's possible to lazy load your store but this has caused me more issues than benefits. For example getting a selected project based on the router url and loaded project entities which mixes two feature stores. The following article has provided me a nice way to split up the store whilst allow any part of the application access to store data:

https://itnext.io/ngrx-best企业角度应用的实践6f00bcdf36d7

对于后代,应用程序结构如下:

For posterity the application structure looks like:

├── app
 │ ├── app-routing.module.ts
 │ ├── app.component.css
 │ ├── app.component.html
 │ ├── app.component.ts
 │ ├── app.module.ts
 │ ├── components
 │ ├── containers
 │ │    └── my-feature
 │ │         ├── my-feature.component.css
 │ │         ├── my-feature.component.html
 │ │         └── my-feature.component.ts
 │ ├── models
 │ │    ├── index.ts
 │ │    └── my-model.ts
 │ │    └── user.ts
 │ ├── root-store
 │ │    ├── index.ts
 │ │    ├── root-store.module.ts
 │ │    ├── selectors.ts
 │ │    ├── state.ts
 │ │    └── my-feature-store
 │ │    |    ├── actions.ts
 │ │    |    ├── effects.ts
 │ │    |    ├── index.ts
 │ │    |    ├── reducer.ts
 │ │    |    ├── selectors.ts
 │ │    |    ├── state.ts
 │ │    |    └── my-feature-store.module.ts
 │ │    └── my-other-feature-store
 │ │         ├── actions.ts
 │ │         ├── effects.ts
 │ │         ├── index.ts
 │ │         ├── reducer.ts
 │ │         ├── selectors.ts
 │ │         ├── state.ts
 │ │         └── my-other-feature-store.module.ts
 │ └── services
 │      └── data.service.ts
 ├── assets
 ├── browserslist
 ├── environments
 │ ├── environment.prod.ts
 │ └── environment.ts
 ├── index.html
 ├── main.ts
 ├── polyfills.ts
 ├── styles.css
 ├── test.ts
 ├── tsconfig.app.json
 ├── tsconfig.spec.json
 └── tslint.json

我应该在哪里小心

where should i be careful

确保您的减速器返回未修改状态的未定义动作.您可以对此进行测试.没有任何借口不测试您的减速器.这些是纯函数,易于测试.

Make sure your reducer returns the state unamended for undefined actions. You can test for this. There's no excuse not to test your reducers. These are pure functions and easy to test.

import * as fromProjects from './project.reducer'
import * as fromProjectState from './project.state'

describe('ProjectReducer', () => {
  describe('undefined action', () => {
    it('should return the default state', () => {
      const { initialState } = fromProjectState
      const action = {} as any
      const state = fromProjects.reducer(initialState, action)

      expect(state).toBe(initialState)
    })
  })
})

花点时间确保您的操作类型正确-错误很难调试.由于重复,您可能会在此处复制并粘贴很多代码.再次可以测试.

Take the time to ensure your actions types are correct - the errors are hard to debug. Due to boilerpate you'll likely copy and paste alot of code here. Again this can be tested.

describe('LoadProjectsFail', () => {
  it('should create an action', () => {
    const payload = { message: 'Load Error ' }
    const action = new fromProjects.LoadProjectsFail(payload)
    expect({ ...action }).toEqual({
      type: fromProjects.LOAD_PROJECTS_FAIL,
      payload,
    })
  })
})

请继续阅读NgRx文档-进行了一些更改,并且教程通常至少落后一个版本.例如

Keep to the NgRx documentation - there's been a few changes and tutorials are normally at least one version behind. e.g.

this.store.pipe(select(projectSelectors.getProjectsLoading))
// versus
this.store.select(projectSelectors.getProjectsLoading)

步骤摘要

与链接几乎相同,但顺序不同:

Pretty much the same as the link but a different order:

根存储

  1. root-store.module.ts

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
import { StoreDevtoolsModule } from '@ngrx/store-devtools'
import { environment } from 'src/environments/environment'
// import { MyFeatureStoreModule } from './my-feature-store/';
// import { MyOtherFeatureStoreModule } from './my-other-feature-store/';

@NgModule({
  imports: [
    CommonModule,
    // MyFeatureStoreModule,
    // MyOtherFeatureStoreModule,
    StoreModule.forRoot({}),
    EffectsModule.forRoot([])
    // Store devtools
    !environment.production
      ? StoreDevtoolsModule.instrument({
          name: 'My App',
        })
      : [],
  ],
  declarations: []
})
export class RootStoreModule {}

添加以下文件,这些文件将开始几乎为空:

Add the following files which will start of pretty much empty:

  • index.ts

    import { RootStoreModule } from './root-store.module'
    import * as RootStoreState from './state'
    import * as RootStoreSelectors from './selectors'
    //export * from './employee'
    //export * from './project'
    //export * from './router'
    export { RootStoreState, RootStoreSelectors, RootStoreModule }

  • state.ts
    • state.ts
    • 
          import { routerState } from './router'
          import { employeeState } from './employee'
          import { projectState } from './project'
      
          export interface State {
            router: routerState.State
            employees: employeeState.State
            projects: projectState.State
          }
      
      

      • selectors.ts
        • selectors.ts
        • 
              import { createSelector } from '@ngrx/store'
              import { Project } from './project/project.model'
              import { routerSelectors } from './router'
              import { projectSelectors } from './project'
          
              export const getSelectedProject = createSelector(
                projectSelectors.getProjectsEntities,
                routerSelectors.getRouterState,
                (entities, router): Project => {
                  return router.state && entities[router.state.params.id]
                }
              )
          
          

          1. RootStoreModule导入app.module.ts

          功能商店

          1. 定义您的功能状态
          2. 定义功能动作
          3. 编写功能效果
          4. 编写您的Feature Reducer(如果可能,请先测试)
          5. 编写您的功能模块
          6. 写入您的index.ts,添加到根index.ts
          7. 将要素状态添加到根状态
          8. 将功能模块声明为Root Store模块的一部分.
          9. 定义功能选择器
          10. 定义任何根选择器(混合功能选择器)
          1. Define your Feature State
          2. Define Feature Actions
          3. Write your Feature Effects
          4. Write your Feature Reducer (Test first if possible)
          5. Write your Feature Module
          6. Write your index.ts, add to root index.ts
          7. Add Feature State to Root State
          8. Declare Feature Module as part of Root Store module.
          9. Define Feature Selectors
          10. Define any Root Selectors (mixes feature selectors)

          这篇关于懒功能模块架构迁移到NGRX:Angular 8的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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