阅读背景:

用Spring Boot & Cloud,Angular2快速搭建微服务web应用 - AngularJS2客户端

来源:互联网 

开发环境搭建

AngularJS2的开发需要node.js环境。在Windows下面安装node.js,最好使用NVM(Node Version Manager)。在这里可以找到NVM的详细信息: https://github.com/creationix/nvm/

安装好NVM之后,用nvm install latest命令,会自动安装最新版本的node.js以及npm。另外还需要在系统的环境变量PATH里面添加node的路径,已方便使用。

实现

建立一个portal目录,并且添加package.json,tsconfig.json,type.json,systemjs.config.js。这些都是AngularJS2项目标准的配置文件,详细信息请参考AngularJS2的快速开始文档: https://angular.io/docs/ts/latest/quickstart.html,只需要修改一下package.json里面的name就可以了。之后在cmd,或者git bash里面,进入portal目录,运行npm install,npm会自动安装AngularJS2所需要的所有依赖包。其它为文件和目录也按照这个快速开始文档建立,包括一个index.html,一个app目录。另外portal下面有app.component.html,app.module.ts,app.routing.ts,main.ts,这些都是每个AngularJS2项目都有的文件。TS文件使用了TypeScript语言,是Angular推荐的语言。其中app.routing.ts定义了网站的路由,具体路由的使用信息请参考: https://angular.io/docs/ts/latest/tutorial/toh-pt5.html。代码里面有一个地方值得提一下,即app.component.html这个文件,实际上做了我们这个单页应用的主视图。所有其它routing里面的视图,都是嵌入到该文件的router-outlet标签的。该标签实际上是一个Angular2的指令,告诉router应该在那里显示视图。具体请参考: https://angular.io/docs/ts/latest/guide/router.html。我们具体看一下AngularJS2调用上节中建立的user-service的代码。这些基本的代码不再一一列出,请参考github上面的代码: https://github.com/cuiwader/healtrav/releases/tag/simple-gateway-no-auth,注意不要使用master HEAD的代码,而是用链接里面这个tag的代码。

shared/user.ts

import { Links } from './links';

export class User {

    constructor (
        public username: string = null,
        public password: string = null,
        public _links: Links = null,
    ) { }
}

TypeScript中,public为默认访问级别,所以不加private就是public的。user.ts导出了User类。与后台的User类相比,少了id属性。前面说过id默认是不导出的,这里遵循这个默认,并且添加了一个_links属性。

/shared/user.service.ts

import { Injectable } from '@angular/core';
import { Headers, Http, RequestOptions, Response } from '@angular/http';

import { User } from './user';
import 'rxjs/add/operator/toPromise';

@Injectable()
export class UserService {

constructor (
private http: Http
) { }

private url = 'https://localhost:8080/user'

getAllUsers(): Promise<User[]> {
return this.http.get(this.url)
.toPromise()
.then(this.extraData)
.catch(this.handleError);
}

private extraData(response: Response) {
return response.json()._embedded['user'];
}

private handleError (error: any) {
let msg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'unknown error';
console.error(msg); // log to console instead
return Promise.reject(msg);
}
}
Angular同样使用了MVC设计模式。所以我们在文件命名中,可以看到.module.ts,.component.ts,.component.html,.service.ts。按照AngularJS的命名习惯,调用后台RESTful API的代码应该放在service里面,并且在需要用到该service的module里面,用@NgModule注释的providers注入。这样该module对应的Component就可以使用了。请参考下面的home.module.ts,home.component.ts,注意UserService类并没有被显式的实例化,而只是在home.module.ts用@NgModule注释进行了依赖注入,然后在HomeModule的构造里面声明了一个private的UserService的成员。另外可以依赖注入的组件,需要用@Injectable注释声明,就像UserService类那样。依赖注入的管理是AngularJS2的一个重要功能。
之后HomeComponent用getAllUsers方法发送GET请求到后台服务,然后解析返回的JSON数据并解析出user数组。

home.module.ts

import { NgModule }       from '@angular/core';
import { CommonModule } from '@angular/common';

import { UserService } from '../shared/user.service';
import { HomeComponent } from './home.component';

@NgModule({
imports: [
CommonModule,
],
declarations: [
HomeComponent,
],
providers: [
UserService
]
})
export class HomeModule { }


home.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';

import { User } from '../shared/user';
import { UserService } from '../shared/user.service';
import { Subscription } from 'rxjs/Subscription' ;

@Component({
templateUrl: '/app/home/home.component.html'
})
export class HomeComponent implements OnInit, OnDestroy {

subscription: Subscription;
users: User[];

constructor(
private router: Router,
private route: ActivatedRoute,
private userService: UserService,
) { }

ngOnInit() {
this.userService.getAllUsers().then(
users => {
console.log(users);
this.users = users;
},
error => console.error(error)
);
}

ngOnDestroy() {
this.subscription.unsubscribe();
}
}
templateURL指明了对应的视图。HomeComponent调用UserService的getAllUsers取得全部user,然后通过视图表现出来。视图大部分的代码跟标准HTML没有区别。AngularJS2最重要的特性之一就是支持双向绑定。目前home.component.html的代码使用的{{ }}只是单向绑定,即从模型到视图。双向绑定的列子我们放到后面。{{ }}相当于ngModel指令。ngFor指令实现了for循环。注意前面的*不能省略。

home.component.html

<div class="container">
<h2>Welcome to Healtrav</h2>

<div class="container">
<h3>All users</h3>
<table>
<ul>
<li *ngFor="let user of users">
<h5>username: {{ user.username }}</h5>
<h5>password: {{ user.password }}</h5>
<h5>_links.self.href: {{ user._links.self.href }}</h5>
</li>
</ul>
</table>
</div>
</div>

该页面显示了系统中所有的用户。

验证

在portal目录下用npm start命令运行,会自动弹出系统默认浏览器,并且打开链接https://localhost:3000
如果是IE浏览器,用户会自动显示出来。如果是chrome浏览器,会发现没有用户显示出来。按F12,会看到如下的错误提示:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

这是因为Spring默认的HTTP Response,不会添加Access-Control-Allow-Origin这个HTTP头。其中一个解决方案是配置Spring,添加这个头,请参考Spring的官方文档:https://spring.io/guides/gs/rest-service-cors/。另外一个解决方案将在下一章讲。


使用Angular-CLI

对于新建项目,一个更好的方式是使用Angular-CLI。只需要几行命令,就可以生成项目的基础文件,减少了开发人员的工作。另外还可以直接打包发布。最新版本的CLI没有使用SystemJS,而是改为用Webpack。Webpack是一个前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。使用CLI的基本步骤:

安装:
npm install -g angular-cli

产生新项目并运行:
ng new PROJECT_NAME
cd PROJECT_NAME
ng serve
打开网页https://localhost:4200/即可以访问。

产生component:
ng g component my-new-component
其它的service,module,等等,都可以用类似的命令产生。

打包:
ng build
之后在dist目录下面产生打包文件。

打包为产品:
ng build --prod --aot

打包时制定index.html的base标签:
ng build --bh /myUrl/

运行测试:
ng test


推荐大家使用CLI工具建立和开发项目。
上一章:用Spring Boot & Cloud,Angular2快速搭建微服务web应用 - 实现RESTful CRUD
下一章:用Spring Boot & Cloud,Angular2快速搭建微服务web应用 - 增加代理服务器

分享到: