三年Angular架构经验总结

  • Post author:
  • Post category:其他


又是许久没有动笔写博客了,18年换了公司,一直很忙。最近临近过年,几个项目也都告一段落,趁着测试和Refactor Code的功夫,想总结一下自己过去三年使用Angular搭建项目的经验。

从当初使用Angular1到现在手里的Angular6,还有已经发布几个月的Angular7,不断迭代的Angular,不断进步,不断优化。

经验的积累使我感受到一个好的Angular项目结构对于开发和维护项目是多么的重要,他能够提升我们的开发效率,团队协作,统一规范,再大型的项目都可以很好的进行协同开发。

目前我负责的项目都会按照以下的结构来搭建:

首先app.routing.ts里面类似这样:

{
    path: 'login',
    canActivate: [IsNotSignedInGuard],
    loadChildren: '../pages/login/login.module#AppLoginModule'
  },
  {
    path: '',
    loadChildren: '../pages/layout/layout.module#AppLayoutModule'
  },
  {
    path: '404',
    loadChildren: '../pages/not-found/not-found.module#NotFoundModule'
  },
  {
    path: 'password',
    loadChildren: '../pages/password/password.module#PasswordModule'
  },
  {path: '**', redirectTo: '404'}

一:概述

这里layout是我们网站的主要布局,比如公共的header,footer,还有各个业务模块都会在里面,而login模块这里因为比较独立,所以设计在layout外部,找不到的路由都会跳转到404页面。canActivate是控制用户是否能够进入路由的权限guard,可以是异步的,比如从后端获取某些权限设置,然后处理权限逻辑,再决定何时执行observer.next(true)即可进入,否则不可进入,并执行你想要的操作。

pages文件夹是业务页面,可能包含非常多的模块,我们采用大家已经很熟悉的懒加载模式,各个模块里面包含各自的页面和组件,相对独立,便于维护不同的模块。如果是这个模块里面公用的组件,则会在这个模块文件夹下建立compoents文件夹,如果是整个项目公用的组件,则放在shared/components文件夹。

各个模块会引入自己需要使用的服务和管道,指令等。管道和指令一般都是整个项目公用的,放在shared文件夹下,遇到少数只有某一个模块特有的,就放在这个模块里面无妨。服务我们根据不同的功能模块,在shared/core文件下面建立各种不同的目录,里面主要包含两类文件,一类是XXXXX.data.ts,也就是model数据层,一类是XXXX.service.ts,也就是请求层。这样结构清晰,纯业务的model和service都在这边,和pages文件分离。类似这样:

二:shared文件

最开始我们需要建立的是shared.module.ts,在这里我们把原本经常在app.module.ts引入的各种基础的,公共的模块在这里统一管理,比如FormsModule,RouterModule,HttpClientModule,TranslateModule,还有全局引入的各种第三方库。

另外就是我们自己写的各种公共的组件,管道,指令,服务都需要在这里引入,声明,导出,方便整个项目使用。类似:


@NgModule({
  imports: [
    RouterModule,
    CommonModule,
    FormsModule,
    HttpClientModule,
    ReactiveFormsModule,
    TranslateModule,
  ],
  declarations: [
    TimeFormatPipe,
    AppLoadingComponent,
    QrCodeDirective,
    DecimalControlDirective,
    MemberStatusPipe,
   
  ],
  exports: [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    TimeFormatPipe,
    AppLoadingComponent,
    TranslateModule,
    DecimalControlDirective,
    MemberStatusPipe,
  ],
  entryComponents: [TwoFactorDialogComponent]
})
export class SharedModule {

  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [
        DecimalPipe,
        HttpClientService,
        CurrencyChannelService,
        UtilsService,
        CookieService,
        LanguageService,
        LinkGuard,
        PrivateAuthBeforeRouteGuard,
        IsNotSignedInGuard,
        InputNumberLimitPipe,
        CurrencyService,
        ExportDataService,
      
      ]
    };
  }
}

然后在app.module.ts里面,我们引入:

    SharedModule.forRoot(),

这样在不同的功能模块里,我们只需要引入SharedModule,而不需要每次都做重复的引入表单等等一些公共的模块。

三:shared下面的各个内容:

1:component文件里面是项目共用的组件,比如loading,网络错误等等。

2:  config文件是各种配置文件,比如一些常量,服务器地址,状态值,等等,基于单一原则,最好按照不同种类分开文件夹。

3:core文件是业务模型,网络请求,根据不同功能模块建立不同文件夹,数据Model和Service放在对应的模块下面。

4:directives是项目共用的指令,主要用来控制DOM变化,比如交互操作,表单输入操作,DOM显示

5:functions里面是公共的方法,比如每个model需要用到的parseData函数,处理解析对象

6:guard是各种路由权限控制逻辑

7:modules是非业务类的公共模块,比如我们封装的动态表单,或者其他的公共模块

8:pipes是公共管道,处理数据格式化

9:services是各种公共服务,比如我们自己封装的HTTP请求,Utils,大多是非业务类的,如果跟业务相关,那么也是比如导出数据这种和具体模块无关的,尽量保持这里的服务具有全局属性。

10:styles文件夹是我们自己的样式文件,比如我们项目的base.scss,button.scss这种。

四:总结

这样一个比较清晰的项目结构就搭建好了,数据和业务分离的非常独立,页面可以很方便的使用各种公共的工具,不需要太多重复的代码。

另外关于项目的数据流,最好全局使用RXJS进行开发,当然,这是另外一个课题了,不过,使用了RXJS来管理数据状态之后,你会爱上它的简洁优雅,函数式编程和强大的性能。

我们使用Angular可以提高我们的开发效率,开发出更好的产品,前提是我们一定要好好的使用它。学习之旅未止,后面我打算开始RXJS的系列博客,深入的总结和学习RX编程思想。



版权声明:本文为liujiawei00原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。