写在前面

由于现在网络上Angular 4的相关技术文档不是很充分,我写出这个采坑的记录文档,一方面是想给自己在项目中遇到的各种问题与个人的理解记录下来,另一方面也想着某些坑大家可能也会遇到,也可以给道友做一个参考。文档中的很多地方多有不足,后期我会慢慢完善,也希望道友们能够及时指出文档中不正确的与可以优化的地方。

我计划将该帮助文档分为4个章节:

章节一:

关于angular 4 + ng-zorro在基础布局与模块拆分上的一些问题与操作步骤

章节二:

angular 4 引入路由=> 组件模块化#module模块化=>  路由模块化(路由按需加载)

章节三:

引入拦截器,统一管理请求与相应

=>

引入http服务进行通讯

=>

引入service服务与后台进行通讯

=>

拆分service服务

=> 

应用观察者模式对数据进行发布与订阅

章节四:

项目打包

=>

优化

============================= Begin ===============================

章节一:关于angular 4 + ng-zorro在基础布局与模块拆分上的一些问题与操作步骤

在使用阿里爸爸推出的Ng-zorro前,希望你先确保本地的angular-cli版本是最新的版本,目前最新的版本为1.6.3(2018/1/10) *兼容问题可能会导致后期项目打包后部门js丢失

如果你本地已经全局安装了cli或者已经使用相对较旧的版本创建了angular 的项目,那么你可以按照下面的命令去更新你本地与项目中的cli版本去兼容ng-zorro:

首先需要先卸载本地的angular-cli安装包:

npm uninstall -g angular-cli
npm uninstall --save-dev angular-cli

在全局安装最新版本的cli包:

npm uninstall -g @angular/cli
npm cache clean
npm install -g @angular/cli@latest

你可以通过cmd命令行,使用 ng -v 去看到本地目前cli的版本。如果你已经安装了最新的版本,你可以使用新版本的ng命令: [ng new "项目名称" ]来创建一个新的angular 项目。如果你已经有angular项目了,那你需要去更新项目中的cli版本。具体的命令如下:

rmdir -rf node_modules dist
npm install --save-dev @angular/cli@latest
npm install

如果你完成了上面的操作,你可以打开package.json来看到你项目中的cli版本已经更换到了最新版本了。

在使用ng-zorro的过程中,需要注意两点:

Ng-zorro并不能一次引入在多组件里进行使用,如果你的项目中存在子module,相关的依赖包需要在子module里进行引入。需要注意的是,你必须在module里通过forRoot()方法去使用。

//主module
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
NgZorroAntdModule.forRoot(),
BrowserAnimationsModule
]

在子module里,就不再需要forRoot()方法了:

//子module
imports: [
CommonModule,
HttpClientModule,
NgZorroAntdModule
]

当你引入了所需的这些文件后,你就可以开始使用ng-zorro了。

章节二:angular 4 引入路由 => 组件模块化#module模块化 =>  路由模块化(路由按需加载)

2.1  angular 4 引入路由

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { NgZorroAntdModule } from 'ng-zorro-antd';
import { RouterModule, Routes } from '@angular/router';
import {HashLocationStrategy , LocationStrategy} from '@angular/common';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
//主module
imports: [
BrowserModule,
FormsModule,
HttpClientModule,
NgZorroAntdModule.forRoot(),
BrowserAnimationsModule
]
//子module
imports: [
CommonModule,
HttpClientModule,
NgZorroAntdModule
],

angular 导入module了之后,一般情况下会将路由单独放在一个文件中进行引入。你需要在主module中进行引入,然后在主module里进行导出,如果你有子module,那么你需要在子module中进行导入,在子module中进行导出,因为Routermodule作为作为管理路由的工作,会将多个模板导入到同一模板中。如果你的项目中需要将路由文件拆分或者如要按需加载与懒加载相关功能,那么这时候你可能需要将路由进行相互关联,在Vue中你可以通过ES6的一些语法进行链接,而angular 4提供了loadChildren来进行响应的相应的链接。具体的代码如下:

  imports: [BrowserModule,FormsModule,HttpClientModule,NgZorroAntdModule.forRoot(),BrowserAnimationsModule,EventAnalysisModule,RouterModule.forRoot(appRoutes)],exports: [RouterModule],
    imports: [CommonModule,FormsModule,ReactiveFormsModule ,NgxEchartsModule,HttpClientModule,NgZorroAntdModule,RouterModule.forChild(EVENTROUTES)],exports: [RouterModule],

routerModule 包含两个关键方法,forRoot(),forChild()

这两个方法,做为控制多个模块在同一模块进行展示,分别在父子module中起到了关键作用,这也是LoadChildren生效的关键步骤。

//路由配置文件{path: 'index',component: NzDemoLayoutTopSide2Component,children: [{path: 'event',loadChildren: './event/eventAnalysis.module#EventAnalysisModule'}]},
//EventAnalysisModule 路由部分{path: 'eventAnalysis',component: EventAanlysisComponent,children: [{path: 'overview',component: OverviewComponent}, {path: 'CreditEvaluation',component: CreditEvaluationComponent}, {path: 'loanHistroy',component: LoanHistroyComponent}, {path: 'userInfo',component: UserInfoComponent}]}

如果你的项目比较大,需要将路由进行模块化或者进行一些懒加载或者按需加载的相关功能,你需要通过loadChildren将路由进行联系。由于loadChildren是需要依赖到最外层路由导入的文件中的,所以你需要将你导入的模块的路径写在路由参数中,而不是通过import的形式导入,并且你需要使用#去分割路径,和导入的模块名。

章节三:

引入拦截器,统一管理请求与相应

如果你使用axios,你可能用过他的拦截功能,允许我们把身份认证,错误处理和服务器状态码等相关问题进行统一处理,而不需要在每个页面去

单独处理,

angular在实现拦截器功能的过程中也非常简单,只需要实现HttpInterceptor接口就可以了。

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {const clonedRequest = req.clone({headers: req.headers.set('Content-Type', 'text/plain;charset=UTF-8')});

而intercept方法则有两个参数,一个是 request,一个是next来调用下一个"中间件"。

按照angular 官网文档的写法,request有一个clone方法,可以去处理我们的请求,并在请求中加入响应的参数,如token, header, 浏览器cookie等

最后,你需要将你的请求参数传递到下一个中间件,而这里则是在return之后进行操作,像这样:

        return next.handle(clonedRequest)

在响应处理的过程中,包含多种情况,你需求将正确的请求返回到相应的组件,将异常的请求进行统一处理,而这个过程则是一

种observable模式,

我们需要用mergeMap, do等rxjs操作符来进行处理。

        return next.handle(clonedRequest).mergeMap((event: any) => {// 处理异常reurn bservable.create(Observable => Observable.next(event));}).catch((res: HttpResponse<any>) => {return Observable.throw(res);})

使用catch进行捕获,返回到组件中。

下面是整个拦截器的代码,需要的话可以进行引入,当然,你还需要现在主Module中进行引入,才能够正常生效:

import { HTTP_INTERCEPTORS } from '@angular/common/http';providers: [MyService, {provide: LocationStrategy, useClass: HashLocationStrategy},{provide: HTTP_INTERCEPTORS,useClass: NoopInterceptor,multi: true,}, ApiModule]

拦截器的代码:

import { Injectable } from '@angular/core';
import { Observable } from "rxjs/Observable";
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/mergeMap';
// thorw方法需要单独引入
import 'rxjs/add/observable/throw';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse} from '@angular/common/http';@Injectable()
export class NoopInterceptor implements HttpInterceptor {intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {const clonedRequest = req.clone({headers: req.headers.set('Content-Type', 'text/plain;charset=UTF-8')});// console.log("new headers", clonedRequest.headers.keys());return next.handle(clonedRequest).mergeMap((event: any) => {// if (event instanceof HttpResponse) {//     return Observable.create(Observable => Observable.error(event));// }return Observable.create(Observable => Observable.next(event));}).catch((res: HttpResponse<any>) => {return Observable.throw(res);})}
}

关于mergeMap和整个拦截器的用法,sf上的大神们也进行了详细的说明:

点击打开链接

引入http服务进行通讯

当你引入angular的拦截器之后,你就可以统一管理所以请求的请求头,并且可以集中处理所有请求的响应体和异常情况了。

那么http请求就变的非常简单了。关于请求的写法,官网和网上有很多的例子,你也可以封装请求方法来进行使用。

引入service服务与后台进行交互

在使用angular4的时候,我想将service做为存储公共数据的地方,那么不同组件的公共的数据和参数,可以存储在service中,

那如果共用的数据总有某些场景下不是最新的,既然是这样,为什么不按照官方的demo那样,将数据源放在service中,之后通过订阅或者

promise的形式去拿到数据呢,这样不同组件在使用一些共用数据的情况下,可以保证是最新数据,使用起来也更方便了。

既然提到了订阅,就不得不说观察者模式了。观察者模式又被称为发布订阅模式。它定义了一种一对一对多的关系网络。简单来说

就是让多个观察者去观察一个对象,当被观察对象发生任何改变的时候,所有订阅了他的观察者们都会及时的收到消息,并及时得到更新。这种

感觉很像订阅报纸一样,订阅报纸后,每当有新报纸出版都会送到你手里,让你知道最新的消息,但是如果你取消订阅报纸,那么你就不会收到最

新版的报纸了。那么这两个角色被观察者和观察者们用什么来表示呢?其实就是subject与observer。关于subject与observer在使用上,sf上

面有很好很全面的介绍:点击打开链接

具体怎么的使用也非常简单,直接上代码:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { ApiModule } from '../api/api';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/retry';@Injectable()// 登录的方法public LoginSubject = new Subject<any>();public getUserInfo(name, pwd):void {var data = {"username":name,"password":pwd};var val = this.HOST.host;this.$http.post(`${val}/login`, data).retry(3).subscribe( res => {this.LoginSubject.next(res)});}

subject是通过new的形式去创建的,那么当你服务端的数据返回之后,你可以使用next将相应流传递到你所定义的subject当中。

服务层的写法就是这样,那么在组件中如何订阅呢?上代码:

            this.service.getUserInfo(name, password)this.subscript = this.service.LoginSubject.subscribe( data => { here is your code }

service需要在构造函数中去声明,这里就不写了。service中的getUserInfo方法接受两个参数,name与password,在这里进行

发布操作,接下来就可以订阅了。由于有些时候,我们会希望在第二次订阅的时候,不会从头开始接收 Observable 发出的值,而是从第一次订

阅当前正在处理的值开始发送,那么就需要对整个过程进行相应的处理。一般来说,我们不会主动去取消订阅,但是根据业务情况不同

我们可能需要去取消订阅,怎么做呢?直接上代码:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { HttpClient, HttpHeaders } from '@angular/common/http'
import { ApiModule } from '../api/api';
import { MyService } from '../myService/service.component';
import {NzMessageService} from 'ng-zorro-antd';
import { Subscription } from 'rxjs/Subscription';@Component({selector: 'login-component',templateUrl: './login.component.html',styleUrls: ['./login.component.less']
})export class LoginComponent implements OnInit {subscript: Subscriptionconstructor (private router:Router,private service: MyService,private _message: NzMessageService,) {this.subscript = new Subscription()}}ngOnInit ():void {this.service.getUserInfo(name, password)this.subscript = this.service.LoginSubject.subscribe( data => {// here is your code}this.subscript.unsubscribe()}}

这就是从创建被观察者oberserver => 发布 => 订阅 => 取消订阅的整个流程。

拆分service服务

当你的业务越来越多的时候,你不可能只用一个service来支撑服务,你需要引入多个service进行与服务端的通讯。service模块化其实很简单,
只要
注意service进行provider的位置就行了,由于项目不同,具体的例子就不列举了。
章节四:打包发布

每次总是小手发抖,担心打包过程中会出现各种各样的问题。我就列举一下一些简单的常见的打包后可能会出现的问题,如果大家没遇到
可以去程序员老黄历查查你今天可能适合打包提测,如果你遇到了那太好了,我就将这些坑分享给道友们。
(1)版本问题
由于整个项目是结合ng-zorro来做的,可能由于cli的版本问题,打包过后如果遇到了部门按钮失效,或者
部门样式丢失的问题,那么你可以尝试去更新一下你全局的cli版本和项目中的cli版本,具体更新的方法,
我在最前面已经写过了。
(2)服务端刷新路由丢失的问题(hash/histroy模式)

导入 HashLocationStrategy 及 HashLocationStrategy,开启hash模式。

import {HashLocationStrategy , LocationStrategy} from '@angular/common';@NgModule({declarations: [AppCmp],bootstrap: [AppCmp],imports: [BrowserModule, routes],providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]
});

再次打包就不会出现刷新后404的问题了。



(3) 服务端打开后无法加载的问题
如果你部署后,根本就打不开,可以检查一下你是否放在服务器根目录的文件中了,如果不是,你可以修改打包后文件中的
index.html,找到

<base href="/">
修改href为'./' 就OK啦

(4) 文件体积过大,优化问题。
你可以通过ng build --prod去开启细编译,他会将你用不到的模块和代码都删掉,--pord默认会开启-aot
编译。

你还可以通过nginx gzip去进行优化操作,这里有一篇道友的文章,对优化进行了很多的处理,很牛,分享给
大家:
点击打开链接


结尾:
这是这次做angular 项目中遇到一些我个人比较印象深刻的问题,记录下来,也分享给大家。都是一些我自己理解的东西和
百度学来
的。可能会有错误,有些代码可能也只供大家参考用。也希望道友们能指出不足之处积极沟通

关于Angular 4 + ng-zorro 使用过程中遇到的问题相关推荐

  1. ngzorro html源码,angular使用NG ZORRO来构建博客展示项目(简单实现展示页面)

    使用 NG ZORRO 在上一篇文章中,我们已经安装了NG ZORRO,并在跟模块中引入了,在子模块中使用还需要再次引入. 编辑layout模块中的header组件 在layout.module.ts ...

  2. angular项目 集成ng zorro 和ng alain

    angular项目 集成 ng zorro和ng alain(mock 和acl权限)学习笔记 这段时间,比较忙,很久没有写博客了.作为后端开发人员,第一次接触angular,以下是个人的学习心得和D ...

  3. angular7中引用ng zorro antd的三种方式

    在新版本的angular中使用新的ng zorro,按照官方文档一步一步来,没有报错,但是也没有反应. 试了一下官方的两种方式,第一种方式如果使用cnpm会报错,第二种方式会没有反应,也是因为使用了c ...

  4. angular ng zorro框架日期框无法自适应宽度的解决方法

    如果我们使用ng zorro框架的日期框时,就会发现,日期框的宽度总是固定的,无法像输入框一样自适应父节点<nz-form-control [nzSpan]="12"> ...

  5. Ng Zorro配置

    Ng Zorro配置 文章目录 Ng Zorro配置 一.app.module里配置 二.引入样式 1.使用全部组件样式 2.引入组件模块 全局安装:npm i ng-zorro-antd g --s ...

  6. ACR2010_MRI骶髂关节炎症与CTX-II变化以及TNF拮抗剂治疗过程中全身炎症改变相关...

    原文 译文 [134] - MRI Inflammation in the Sacroiliac Joints Is Associated with CTX-II and Changes in Sys ...

  7. linux存储库rep 61082,安装informatic过程中的错误

    1.Check if the DISPLAY variable is set export DISPLAY=192.168.3.201:0.0 在注销用户并切换到oracle或者infa 用户,就可以 ...

  8. Ghost过程中出现GHOSTERR.TXT文件的解决方法

    强文:Ghost过程中出现GHOSTERR.TXT文件的解决方法 注:这是篇绝强的文章,作者不明,在好几个老论坛都有转载,反应很热烈,给大家共享一下小人物,大博客0Qo-GUu9F+rR :p$gY& ...

  9. 资深数据科学家教你如何在求职过程中找到心仪工作

    目前进入七月份,算是又一年秋招的开始,实习的中期阶段.很有必要给大家分享一下这篇来自数据科学家Kelly Peng的求职心路历程,她应聘于她所喜爱的Airbnb公司的数据科学岗位,即使你想应聘的不是数 ...

最新文章

  1. php中strtotime的意思,php中strtotime函数用法详解
  2. java 窗口GUI
  3. 一键部署VS插件:让.NET开发者更幸福
  4. jboss调jvm参数_在同一台机器上启动多个JBoss A-MQ JVM
  5. 其他团队对本团队评价的总结
  6. [html] 说说你对Media Source Extensions(MSE)的理解,它解决了什么问题呢?
  7. 捕获Wscript.Quit的退出码
  8. linux vi 编辑器用法
  9. Vlan配置详解之三层交换
  10. Sublime功能拓展及插件
  11. Angular - - ng-focus、ng-blur
  12. Java 定时任务@Scheduled使用
  13. mysql静默安装_Windows环境Mysql静默安装
  14. [求助]python模拟布丰投针
  15. Linux cd命令cd、 cd ~、cd /、cd../、cd /home讲解
  16. java写入文件中文乱码问题_解决 JAVA 写入文本文件时中文乱码
  17. java aspose 给Word添加水印
  18. 软件产品选型测试/POC测试
  19. allow_url_include和allow_url_fopen 详解
  20. 设计模式(Design Pattern)详细整理(含思维导图)

热门文章

  1. 计算机毕业设计Node.js+Express母婴商品店进出货管理系统(源码+程序+lw+远程调试)
  2. 统计量分析--极差、标准差、变异系数、四分位数间距
  3. php中soap使用,SoapServer服务端编写,SoapClient客户端编写
  4. 网页消重算法(via北大天网课题组)
  5. .o/.obj 文件的组成格式
  6. C#入门学习-----制作AVI播放器
  7. 闪迪u盘格式化 linux,u盘格式化工具安卓版闪迪u盘64g 3.0高速
  8. 前端JS常用工具方法
  9. 最新卡巴杀毒软件,可以免费升级哦,卡巴斯基激活码(2007年4月23号更新)
  10. pythoncqt_Python數據分析師-機器學習數據辨識篇