在上一篇文章使用 Angular 2 开发单页应用程序之二 中,我们已经完成了自定义组件的开发。
dw-ng2-app 中包含了三个业务组件:
- 天气
- 电影
- 货币
接下来我们将创建业务组件的服务。
创建服务
按 Ctrl-C 停止 Angular 进程。在命令提示符下,执行以下命令创建服务。
ng g service Shared --spec false
在根模块文件夹中创建了Shard服务,服务位于 shared.service.ts 文件中。下面修改文件内容如下:
import { Injectable } from '@angular/core';
import { Http, Headers, Response } from "@angular/http";
import 'rxjs/Rx';
import { Observable } from "rxjs";
@Injectable()
export class SharedService {
weatherURL1 = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22";
weatherURL2 = "%2C%20";
weatherURL3 = "%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
findMovieURL1 = "http://www.omdbapi.com/?t=";
findMovieURL2 = "&y=&plot=short&r=json";
currencyURL = "http://api.fixer.io/latest?symbols=";
totReqsMade: number = 0;
constructor(private _http: Http) { }
findWeather(city, state) {
this.totReqsMade = this.totReqsMade + 1;
return this._http.get(this.weatherURL1 + city + this.weatherURL2+ state + this.weatherURL3)
.map(response => {
{ return response.json() };
})
.catch(error => Observable.throw(error.json()));
}
findMovie(movie) {
this.totReqsMade = this.totReqsMade + 1;
return this._http.get(this.findMovieURL1 + movie + this.findMovieURL2)
.map(response => {
{ return response.json() };
})
.catch(error => Observable.throw(error.json().error));
}
getCurrencyExchRate(currency) {
this.totReqsMade = this.totReqsMade + 1;
return this._http.get(this.currencyURL + currency)
.map(response => {
{ return response.json() };
})
.catch(error => Observable.throw(error.json()));
}
}
- import ... 语句是任何服务正常运行所必不可少的。
- @Injectable() 语句特别重要;它表明此 service 可注入到其他组件中 — 该技术通常被称为依赖注入。
- 服务中定义了 3 个方法,它们的名称表明了自己的功能。在方法执行时,Angular 将让浏览器访问网络来使用Yahoo提供的服务 API。
我们现在把组件链接到所创建的服务上。
修改 movie.component.ts 如下:
import { Component, OnInit } from '@angular/core';
import { SharedService } from "./../shared.service";
@Component({
selector: 'app-movie',
templateUrl: './movie.component.html',
styles: []
})
export class MovieComponent implements OnInit {
id_movie: string = "";
mv_Title: string = "";
mv_Rated: string = "";
mv_Released: string = "";
mv_Director: string = "";
mv_Actors: string = "";
mv_Plot: string = "";
constructor(private _sharedService: SharedService) {
}
ngOnInit() {
}
callMovieService() {
this._sharedService.findMovie(this.id_movie)
.subscribe(
lstresult => {
this.mv_Title = lstresult["Title"];
this.mv_Rated = lstresult["Rated"];
this.mv_Released = lstresult["Released"];
this.mv_Director = lstresult["Director"];
this.mv_Actors = lstresult["Actors"];
this.mv_Plot = lstresult["Plot"];
},
error => {
console.log("Error. The findMovie result JSON value is as follows:");
console.log(error);
}
);
}
}
修改 weather.component.ts 如下:
import { Component, OnInit } from '@angular/core';
import { SharedService } from "./../shared.service";
@Component({
selector: 'app-weather',
templateUrl: './weather.component.html',
styles: []
})
export class WeatherComponent implements OnInit {
id_city: string = "";
id_state: string = "";
op_city: string = "";
op_region: string = "";
op_country: string = "";
op_date: string = "";
op_text: string = "";
op_temp: string = "";
constructor(private _sharedService: SharedService) {
}
ngOnInit() {
}
callWeatherService() {
this._sharedService.findWeather(this.id_city, this.id_state)
.subscribe(
lstresult => {
this.op_city = lstresult["query"]["results"]["channel"]["location"]["city"];
this.op_region = lstresult["query"]["results"]["channel"]["location"]["region"];
this.op_country = lstresult["query"]["results"]["channel"]["location"]["country"];
this.op_date = lstresult["query"]["results"]["channel"]["item"]["condition"]["date"];
this.op_text = lstresult["query"]["results"]["channel"]["item"]["condition"]["text"];
this.op_temp = lstresult["query"]["results"]["channel"]["item"]["condition"]["temp"];
},
error => {
console.log("Error. The findWeather result JSON value is as follows:");
console.log(error);
}
);
}
}
修改 currency.component.ts 如下:
import { Component, OnInit } from '@angular/core';
import { SharedService } from "./../shared.service";
@Component({
selector: 'app-currency',
templateUrl: './currency.component.html',
styles: []
})
export class CurrencyComponent implements OnInit {
id_currency: string = "";
my_result: any;
constructor(private _sharedService: SharedService) {
}
ngOnInit() {
}
callCurrencyService() {
this._sharedService.getCurrencyExchRate(this.id_currency.toUpperCase())
.subscribe(
lstresult => {
this.my_result = JSON.stringify(lstresult);
},
error => {
console.log("Error. The callCurrencyService result JSON value is as follows:");
console.log(error);
}
);
}
}
更新 app.module.ts 以引入 Shared 服务,如下所示添加以下两行,
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { MenuComponent } from './menu.component';
import { WeatherComponent } from './weather/weather.component';
import { CurrencyComponent } from './currency/currency.component';
import { MovieComponent } from './movie/movie.component';
import { CONST_ROUTING } from './app.routing';
import { SharedService } from "./shared.service"; // 新添加
@NgModule({
declarations: [
AppComponent,
MenuComponent,
WeatherComponent,
CurrencyComponent,
MovieComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
CONST_ROUTING
],
providers: [SharedService], // 新添加
bootstrap: [AppComponent]
})
export class AppModule { }
修改组件视图
现在在HTML视图中调用 Shared 服务的方法。
修改 movie.component.html 如下,
<h2>Open Movie Database</h2>
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<input type="text" required [(ngModel)]="id_movie" (change)="callMovieService()" class="form-control" placeholder="Enter Movie name ...">
<br><br>
<h3>Movie Details</h3>
<br>
<p class="well lead">
<i> Title :</i> {{ this.mv_Title }} <br>
<i> Plot :</i> {{ this.mv_Plot }} <br>
<i> Actors :</i> {{ this.mv_Actors }} <br>
<i> Directed by :</i> {{ this.mv_Director }} <br>
<i> Rated :</i> {{ this.mv_Rated }} <br>
<i> Release Date :</i> {{ this.mv_Released }} <br>
</p>
<p class="text-info">Total # of all the service requests including Weather, Movie, and Currency is :
<span class="badge">{{this._sharedService.totReqsMade}}</span>
</p>
</div>
</div>
修改 weather.component.html 如下,
<h2>Yahoo! Weather </h2>
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<input type="text" [(ngModel)]="id_city" class="form-control" placeholder="Enter City name ..."><br>
<input type="text" [(ngModel)]="id_state" class="form-control" placeholder="Enter State. Example CA for California ..."><br>
<button type="button" class="btn btn-primary" (click)="callWeatherService()">Submit</button>
<br><br><br>
<br>
<p class="well lead">
<i>City, State, Country :</i> {{ this.op_city }} {{ this.op_region }} {{ this.op_country }} <br>
<i>Current Condition :</i> {{ this.op_text }} <br>
<i>Current Temperature :</i> {{ this.op_temp }} <br>
</p>
<p class="text-info">Total # of all the service requests including Weather, Movie, and Currency is :
<span class="badge">{{this._sharedService.totReqsMade}}</span>
</p>
</div>
</div>
修改 currency.component.html 如下,
<h2>Currency Exchange Rates</h2>
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<input type="text" [(ngModel)]="id_currency" (change)="callCurrencyService()" class="form-control" placeholder="Enter Currency Symbol. Example: GBP(,AUD,INR)...">
<br><br>
<h3>Rate Details</h3>
<br>
<p class="well lead">Exchange rate relative to Euro in a JSON format: : {{ this.my_result }} </p>
<p class="text-info">Total # of all the service requests including Weather, Movie, and Currency is :
<span class="badge">{{this._sharedService.totReqsMade}}</span>
</p>
</div>
</div>
完成以上的开发后,dw-ng2-app 就可以在浏览器接受用户的输入了。
运行应用程序
启动应用程序,在浏览器里面输入一些信息,查看结果。例如,在 Weather 页面,输入 San Francisco 来查看该城市的天气情况:
工作正常,但我们还可以让 UI 更具吸引力。改进 GUI 的一种方法是使用 Bootstrap,改进以后的页面如下,
结束语
我们学习了如何使用 Angular 2 编写一个 SPA,并在开发计算机和沙箱服务器中运行它。
对于实际业务需求,可能还需要服务端的功能支持,来提供如身份验证、业务功能等服务。这些服务器端技术,可以使用 Node.js,也可以使用 Java、PHP等。
在应用程序性能方面的,可以继续关注和研究以下方面:
- 捆绑:该进程将您的许多程序组合到一个文件中。
- 微型化:压缩捆绑的文件,以便尽可能地减小项目大小。
- 提前 (AoT) 编译:服务器复杂在构建过程中提前编译,而不是浏览器在运行时期间执行即时 (JIT) 编译。
文章导航
进一步的学习
免费获取项目源代码,咨询老师进行答疑指导,请加QQ:1628145742 ,或报名我们的实战课程: