由于项目升级的需要,项目前端架构使用的Angular2的MVVM框架,先将再项目中遇到的一些问题和部分学习笔记整理以下,写成博客,方便以后查看。
AngularJs2是急于Node.JS的基本框架,现在大部分前端框架都基于此,Node.JS入门在之前的文章中提到过。
TypeScript
TypeScript 是一种由微软开发的自由和开源的编程语言,它是JavaScript的一个超集,扩展了JavaScript的语法。
JavaScript 与 TypeScript 的区别
TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。 TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。
TypeScript语法特性
-
类 Classes
-
接口 Interfaces
-
模块 Modules
-
类型注解 Type annotations
-
编译时类型检查 Compile time type checking
-
Arrow 函数 (类似 C# 的 Lambda 表达式)
在后面的讲解中,我会对上面这些特性进行详细说明。
创建Angular项目
Angular2 已经支持angular-cli快速创建项目,我们只需全局安装cli,代码如下
npm install -g @angular/cli
然后进入响应的文件夹中,运行
ng new my-app
里面会让大家进行一些选项的选择,这个根据个人需要自行选择,然后就快速创建了一个AngularJS2的项目了。
配置文件解释
Angular 项目需要以下几个配置文件:
- package.json =》 标记本项目所需的 npm 依赖包。
- tsconfig.json =》 定义了 TypeScript 编译器如何从项目源文件生成 JavaScript 代码。
- typings.json =》 为那些 TypeScript 编译器无法识别的库提供了额外的定义文件。
- systemjs.config.js =》 为模块加载器提供了该到哪里查找应用模块的信息,并注册了所有必备的依赖包。 它还包括文档中后面的例子需要用到的包。
Angular2 基本架构
Angular 2 应用程序应用主要由以下 8 个部分组成:
- 模块 (Modules)
- 组件 (Components)
- 模板 (Templates)
- 元数据 (Metadata)
- 数据绑定 (Data Binding)
- 指令 (Directives)
- 服务 (Services)
- 依赖注入 (Dependency Injection)
下图展示了每个部分是如何相互工作的:
模块 Modules
每一个Angular2的项目中,<font color=#FF0000>必定</font>含有一个.module.ts的文件,里面装载了这个项目所需要的所有模块和组件。
Angular 应用是由模块化的,它有自己的模块系统:NgModules。
每个 Angular 应该至少要有一个模块(根模块),一般可以命名为:AppModule。
几个重要的属性如下:
-
declarations (声明) - 视图类属于这个模块。 Angular 有三种类型的视图类: 组件 、 指令 和 管道 。
-
exports - 声明( declaration )的子集,可用于其它模块中的组件模板 。
-
imports - 本模块组件模板中需要由其它导出类的模块。
-
providers - 服务的创建者。本模块把它们加入全局的服务表中,让它们在应用中的任何部分都可被访问到。
-
bootstrap - 应用的主视图,称为根组件,它是所有其它应用视图的宿主。只有根模块需要设置 bootstrap 属性中。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ Logger ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
组件 Components
-
组件是一个模板的控制类用于处理应用和逻辑页面的视图部分。是构成 Angular 应用的基础和核心,可用于整个应用程序中。
-
组件知道如何渲染自己及配置依赖注入。
-
组件通过一些由属性和方法组成的 API 与视图交互。
创建 Angular 组件的方法有三步:
- 从 @angular/core 中引入 Component 修饰器
- 建立一个普通的类,并用 @Component 修饰它
- 在 @Component 中,设置 selector 自定义标签,以及 template 模板
模板 Templates
-
Angular模板的默认语言就是HTML。
-
我们可以通过使用模板来定义组件的视图来告诉 Angular 如何显示组件。以下是一个简单是实例:
元数据 Metadata
-
元数据告诉 Angular 如何处理一个类。
-
考虑以下情况我们有一个组件叫作 Component ,它是一个类,直到我们告诉 Angular 这是一个组件为止。
-
你可以把元数据附加到这个类上来告诉 Angular Component 是一个组件。
-
在 TypeScript 中,我们用 装饰器 (decorator) 来附加元数据。
来一段简单的代码
@Component({
selector : 'mylist',
template : '<h2>菜鸟教程</h2>'
directives : [ComponentDetails]
})
export class ListComponent{...}
@Component 装饰器能接受一个配置对象,并把紧随其后的类标记成了组件类。
Angular 会基于这些信息创建和展示组件及其视图。
@Component 中的配置项说明:
-
selector - 一个 css 选择器,它告诉 Angular 在 父级 HTML 中寻找一个
标签,然后创建该组件,并插入此标签中。 -
templateUrl - 组件 HTML 模板的地址。
-
directives - 一个数组,包含 此 模板需要依赖的组件或指令。
-
providers - 一个数组,包含组件所依赖的服务所需要的依赖注入提供者。
数据绑定 Data binding
-
数据绑定为应用程序提供了一种简单而一致的方法来显示数据以及数据交互,它是管理应用程序里面数值的一种机制。
-
通过这种机制,可以从HTML里面取值和赋值,使得数据的读写,数据的持久化操作变得更加简单快捷。
-
如图所示,数据绑定的语法有四种形式。每种形式都有一个方向——从 DOM 来、到 DOM 去、双向,就像图中的箭头所示意的。
- 在相对比较复杂的页面渲染上,减少了数据交互的必要性,减轻了服务器的压力,使得应用更加的流畅,提高用户的体验度。
指令 Directives
Angular模板是动态的 。当 Angular 渲染它们时,它会根据指令对 DOM 进行修改。
指令是一个带有”指令元数据”的类。在 TypeScript 中,要通过 @Directive 装饰器把元数据附加到类上。
在Angular中包含以下三种类型的指令:
- 属性指令:以元素的属性形式来使用的指令。
- 结构指令:用来改变DOM树的结构
- 组件:作为指令的一个重要子类,组件本质上可以看作是一个带有模板的指令。
<li *ngFor="let site of sites"></li> <site-detail *ngIf="selectedSite"></site-detail>
上述代码中,
- *ngFor 告诉 Angular 为 sites 列表中的每个项生成一个 li 标签。
- *ngIf 表示只有在选择的项存在时,才会包含 SiteDetail 组件。
依赖注入
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫”依赖查找”(Dependency Lookup)。
通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
在传统的开发模式中,调用者负责管理所有对象的依赖,循环依赖一直是梦魇,而在依赖注入模式中,这个管理权交给了注入器(Injector),它在软件运行时负责依赖对象的替换,而不是在编译时。这种控制反转,运行注入的特点即是依赖注入的精华所在。
Angular 能通过查看构造函数的参数类型,来得知组件需要哪些服务。 例如, SiteListComponent 组件的构造函数需要一个 SiteService:
constructor(private service: HeroService) { }
当 Angular 创建组件时,会首先为组件所需的服务找一个注入器( Injector ) 。
注入器是一个维护服务实例的容器,存放着以前创建的实例。
如果容器中还没有所请求的服务实例,注入器就会创建一个服务实例,并且添加到容器中,然后把这个服务返回给 Angular 。
当所有的服务都被解析完并返回时, Angular 会以这些服务为参数去调用组件的构造函数。 这就是依赖注入 。
简单的代码实例
import { Component, OnInit } from '@angular/core';
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { JhiEventManager } from 'ng-jhipster';
import { Account, LoginModalService, Principal } from '../shared';
@Component({
selector: 'jhi-home',
templateUrl: './home.component.html',
styleUrls: [
'home.scss'
]
})
export class HomeComponent implements OnInit {
account: Account;
modalRef: NgbModalRef;
constructor(
private principal: Principal,
private loginModalService: LoginModalService,
private eventManager: JhiEventManager
) {
}
ngOnInit() {
this.principal.identity().then((account) => {
this.account = account;
});
this.registerAuthenticationSuccess();
}
}
上述代码是表示一个简单的component.ts, 在Angular中,一个component.ts 必定包含一个component.html。
但一个模块不能只由component组成,一个基本的模块结构应该如下所示:
- component负责基本的试图逻辑
- model负责前端实体(非必须)
- module负责整合该模块用到的组件,服务等信息,并暴露给上一层
- route 负责页面之间的路由信息
- service 负责与后台交互
- index 是这个模块的入口和出口
Angular路由
router.ts 详尽的描述了该模块的跳转动作。
- 通过path获取对应的路径名称
- 通过component指定到对应的组件
- data指进入该组件所需的参数信息。
直接上代码,通俗易懂:
export const departmentRoute: Routes = [
{
path: 'department',
component: DepartmentComponent,
resolve: {
'pagingParams': DepartmentResolvePagingParams
},
data: {
authorities: ['ROLE_USER'],
pageTitle: 'warehouseApp.department.home.title'
},
canActivate: [UserRouteAccessService]
}, {
path: 'department/:id',
component: DepartmentDetailComponent,
data: {
authorities: ['ROLE_USER'],
pageTitle: 'warehouseApp.department.home.title'
},
canActivate: [UserRouteAccessService]
}
];
服务 Service
Angular 通过HttpClient与后台进行交互,其底层还是Ajax的基本原理,但对其进行了些许封装
废话不多说,直接上代码:
Angular插件
Angular之所以强大,不仅仅是因为他的MVVM模式,同时它还有很多的插件和组件供大家使用,这里推荐几个供大家参考
- PrimeNG Angular 强大的UI组件,是Angular非常重要的一部分
- ng2-file-upload 文件上传插件,非常强大
- ng2-pdf-viewer pdf预览,和将html转换乘pdf,具体可以参考教程
如果有很好的插件推荐,希望您能联系我,Email:pandapanzhu@163.com