美文网首页ABP我爱编程
abp & ng-alain 改造前端 二 —— 初始化

abp & ng-alain 改造前端 二 —— 初始化

作者: 诸葛_小亮 | 来源:发表于2018-06-19 07:32 被阅读290次

    介绍

    ABP 是 ASP.NET Boilerplate Project(Asp.net 样板项目)的简称,网址:http://aspnetboilerplate.com/
    ng-alain 是基于 antd 中后台前端解决方案,网址:https://ng-alain.com/
    官方网页下载的项目的angular项目是基于(AdminBSB:https://github.com/gurayyarar/AdminBSBMaterialDesign)

    1. 目录:https://www.jianshu.com/p/589af988637c
    2. 源代码:https://github.com/ZhaoRd/abp-alain

    前期准备

    在《abp & ng-alain 改造前端 一 —— 项目准备》里,我们将项目已经准备好,接下来我们查看angular项目的运行方式,并将代码迁移至 abpalain中。
    在安装完jquery、abp、moment 等依赖包之后,我们需要在typings.d.ts中定义信息,以便能够在typescript中使用第三方依赖库,添加内容如下

    // # 3rd Party Library
    // If the library doesn't have typings available at `@types/`,
    // you can still use it by manually adding typings for it
    ///<reference path="../node_modules/@types/jquery/index.d.ts"/>
    ///<reference path="../node_modules/abp-web-resources/Abp/Framework/scripts/abp.d.ts"/>
    ///<reference path="../node_modules/abp-web-resources/Abp/Framework/scripts/libs/abp.jquery.d.ts"/>
    ///<reference path="../node_modules/moment/moment.d.ts"/>
    ///<reference path="../node_modules/@types/moment-timezone/index.d.ts"/>
    
    // Typings reference file, see links for more information
    // https://github.com/typings/typings
    // https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html
    
    declare var System: any;
    
    declare var App: any; //Related to Metronic
    declare var Layout: any; //Related to Metronic
    
    declare var Push: any;
    
    interface JQuery {
        countTo(...any): any;
    }
    
    interface JQuery {
        sparkline(...any): any;
    }
    
    interface JQueryStatic {
        AdminBSB: any;
    }
    

    为了能够快捷定位到文件,还需要在文件tsconfig.app.json中添加一下信息

    "@abp/*": [ "../node_modules/abp-ng2-module/dist/src/*" ],
     "@node_modules/*": [ "../node_modules/*" ],
    

    添加成功后的完整代码如下


    完整代码

    分析angular项目

    1. 找到项目入口
      分析angular入口程序,一般是src下的main.ts文件,代码如下

      main.ts
      通过该文件,我们可以看到,在main.ts中,angualr启动RootModule作为主模块
    2. RootModule
      root.module.ts文件代码如下

    import { BrowserModule } from '@angular/platform-browser';
    import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    import { NgModule, Injector, APP_INITIALIZER, LOCALE_ID } from '@angular/core';
    
    import { AbpModule } from '@abp/abp.module';
    import { AbpHttpInterceptor } from '@abp/abpHttpInterceptor';
    import { HTTP_INTERCEPTORS } from '@angular/common/http';
    
    import { SharedModule } from '@shared/shared.module';
    import { ServiceProxyModule } from '@shared/service-proxies/service-proxy.module';
    import { RootRoutingModule } from './root-routing.module';
    
    import { AppConsts } from '@shared/AppConsts';
    import { AppSessionService } from '@shared/session/app-session.service';
    import { API_BASE_URL } from '@shared/service-proxies/service-proxies';
    
    import { RootComponent } from './root.component';
    import { AppPreBootstrap } from './AppPreBootstrap';
    import { ModalModule } from 'ngx-bootstrap';
    import { HttpClientModule, HttpResponse } from '@angular/common/http';
    
    export function appInitializerFactory(injector: Injector) {
      return () => {
    
        abp.ui.setBusy();
        return new Promise<boolean>((resolve, reject) => {
          AppPreBootstrap.run(() => {
            abp.event.trigger('abp.dynamicScriptsInitialized');
            var appSessionService: AppSessionService = injector.get(AppSessionService);
            appSessionService.init().then(
              (result) => {
                abp.ui.clearBusy();
                resolve(result);
              },
              (err) => {
                abp.ui.clearBusy();
                reject(err);
              }
            );
          });
        });
      }
    }
    
    export function getRemoteServiceBaseUrl(): string {
      return AppConsts.remoteServiceBaseUrl;
    }
    
    export function getCurrentLanguage(): string {
        return abp.localization.currentLanguage.name;
    }
    
    @NgModule({
      imports: [
        BrowserModule,
        BrowserAnimationsModule,
        SharedModule.forRoot(),
        ModalModule.forRoot(),
        AbpModule,
        ServiceProxyModule,
        RootRoutingModule,
        HttpClientModule
      ],
      declarations: [
        RootComponent
      ],
      providers: [
        { provide: HTTP_INTERCEPTORS, useClass: AbpHttpInterceptor, multi: true },
        { provide: API_BASE_URL, useFactory: getRemoteServiceBaseUrl },
        {
          provide: APP_INITIALIZER,
          useFactory: appInitializerFactory,
          deps: [Injector],
          multi: true
        },
          {
              provide: LOCALE_ID,
              useFactory: getCurrentLanguage
          }
      ],
      bootstrap: [RootComponent]
    })
    export class RootModule {
    
    }
    
    

    我们主要关注以下内容


    初始化
    初始化方法

    上面两个片段说明,angular在启动的时候,提供了一个钩子,以前angular程序在启动之前,能够做自定义的初始化内容。

    以上便是整个angular启动的过程,接下来 ,我们将该步骤,迁移到abpalain项目中


    复制项目

    1. AppPreBootstrap.ts复制到abpalin项目下的src文件加下

      AppPreBootstrap
    2. 将 angular项目下的 src\shared中的所有文件,复制到abpalain项目下的src\app\shared中,注意 shared.module.ts 文件,由于abpalain在该文件加下已经有一个shared.module.ts 文件,所以需要在复制前修改名称为:abpshared.module.ts

    3. 修改abpshared.module.ts模块名称,将该文件中的导出类,重命名为:AbpSharedModule
      修改完毕的代码如下

    import { CommonModule } from '@angular/common';
    import { NgModule, ModuleWithProviders } from '@angular/core';
    import { AbpModule } from '@abp/abp.module';
    import { RouterModule } from '@angular/router';
    
    import { AppSessionService } from './session/app-session.service';
    import { AppUrlService } from './nav/app-url.service';
    import { AppAuthService } from './auth/app-auth.service';
    import { AppRouteGuard } from './auth/auth-route-guard';
    
    import { AbpMessage } from './abpmessage/AbpMessage';
    
    @NgModule({
        imports: [
            CommonModule,
            AbpModule,
            RouterModule
        ],
        declarations: [
            
        ],
        exports: [
            
        ]
    })
    export class AbpSharedModule {
        static forRoot(): ModuleWithProviders {
            return {
                ngModule: AbpSharedModule,
                providers: [
                    AppSessionService,
                    AppUrlService,
                    AppAuthService,
                    AppRouteGuard,
                    AbpMessage
                ]
            }
        }
    }
    
    
    1. 修改 app.module.ts 文件,添加abpsharedmodule的依赖,添加abp模块的依赖


      app.module.ts

    扩展 abplain项目的启动

    app.module.ts中,查看启动程序的方式

    启动方式 启动方法

    分析可知,该代码将StartupService中的load方法作为启动方法的,那么如何扩展ABP的启动方式呢?

    添加Injector依赖

    需要改造 StartupServiceFactory方法,添加对Injector的依赖,见第151行

    image.png
    修改StartupServiceFactory方法,添加Injector,如下代码
    export function StartupServiceFactory(
      injector: Injector,
      startupService: StartupService,
    ): Function 
    

    启动ABP

    查看startupService.load()方式返回结果的格式是:Promise,这也意味着,我们可以使用一下方式来启动



    修改网络访问地址

    ng-alain中,使用了两个http拦截器:SimpleInterceptorDefaultInterceptor,需要将这两个拦截器注释,添加ABP的拦截器代码


    修改完http拦截器之后,还需要定义API访问的BaseUrl,内容如下


    修改完毕后的代码如下:



    运行

    使用命令: npm start,如果浏览器出现如下界面表示运行成功

    运行界面

    F12 查看网路请求


    网络请求

    通过网络请求,可以看到,abpalain项目已经在程序启动的时候进行abp后端接口的访问


    弹出框提示和提醒

    得益于ABP作者的高度可扩展的思想,我们可以在不依赖notify等组件的情况下,将弹出框提示和提醒,自定义 扩展为 antd样式
    在shared中新建AbpMessage类,代码如下

    import { Injectable } from '@angular/core';
    import { NzModalService ,NzNotificationService ,NzMessageService } from 'ng-zorro-antd';
    import { reverse } from 'dns';
    import { reject } from 'q';
    
    @Injectable()
    export class AbpMessage {
    
    
        constructor(private modalService: NzModalService,
        private messageService:NzMessageService) {
        }
    
        init(){
            
            this.initMessage();
            this.initNotify();
        }
    
        initNotify(){
            abp.notify.info=(message: string, title?: string)=>{
                this.messageService.create('info', message);
            }
            abp.notify.success=(message: string, title?: string)=>{
                this.messageService.create('success', message);
            }
            abp.notify.warn=(message: string, title?: string)=>{
                this.messageService.create('warn', message);
            }
            abp.notify.error=(message: string, title?: string)=>{
                this.messageService.create('error', message);
            }
        }
    
        initMessage(){
            abp.message.info = (message, title)=>{
                var dispalyTitle = title==null?message:title;
                this.modalService.info({
                    nzTitle: dispalyTitle,
                    nzContent: message,
                    nzOnOk: () => console.log('Info OK')
                  });
              };
    
              abp.message.success = (message, title)=>{
                var dispalyTitle = title==null?message:title;
                this.modalService.success({
                    nzTitle: dispalyTitle,
                    nzContent: message
                  });
              };
    
              abp.message.warn = (message, title)=>{
                var dispalyTitle = title==null?message:title;
                this.modalService.warning({
                    nzTitle: dispalyTitle,
                    nzContent: message
                  });
              };
    
              abp.message.error = (message, title)=>{
                var dispalyTitle = title==null?message:title;
                this.modalService.error({
                    nzTitle: dispalyTitle,
                    nzContent: message
                  });
              };
    
              abp.message.confirm=(message)=>{
    
                return new Promise<boolean>((reverse,reject)=>{
    
                    this.modalService.confirm({
                        // nzTitle: '<i>Do you Want to delete these items?</i>',
                         nzContent: message,
                         nzOnOk: () => reverse(true),
                         nzOnCancel: () => reverse(false)
                       });
    
                })
    
              }
            
        }
    
    }
    

    代码中的核心是替换abp框架定义的函数



    测试弹出框提示和提醒

    在程序启动的时候,需要添加AbpMessage初始化的代码

    image.png

    在添加链式调用,以便测试AbpMessage是否生效

    运行结果如下


    经过上面的改造,已经成功替换 abp中的弹出框提示和提醒功能,在后面的模块中,可以直接使用 abp.messageabp.notify

    总结

    该篇主要分享了如何参考angular项目改造ng-alain项目启动的过程,经过这篇文章,我们已经初步掌握了abp前端项目的启动流程,接下来进入页面改造工作。


    我的公众号

    我的公众号

    源代码

    源代码:https://github.com/ZhaoRd/abp-alain

    相关文章

      网友评论

        本文标题:abp & ng-alain 改造前端 二 —— 初始化

        本文链接:https://www.haomeiwen.com/subject/mtioeftx.html