使用 Angular 2 開發(fā)單頁(yè)應(yīng)用程序之三

在上一篇文章使用 Angular 2 開發(fā)單頁(yè)應(yīng)用程序之二 中,我們已經(jīng)完成了自定義組件的開發(fā)疮茄。
dw-ng2-app 中包含了三個(gè)業(yè)務(wù)組件:

  • 天氣
  • 電影
  • 貨幣
    接下來我們將創(chuàng)建業(yè)務(wù)組件的服務(wù)坊秸。

創(chuàng)建服務(wù)

按 Ctrl-C 停止 Angular 進(jìn)程泡嘴。在命令提示符下,執(zhí)行以下命令創(chuàng)建服務(wù)辑畦。

ng g service Shared --spec false

在根模塊文件夾中創(chuàng)建了Shard服務(wù)羞反,服務(wù)位于 shared.service.ts 文件中布朦。下面修改文件內(nèi)容如下:

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 ... 語(yǔ)句是任何服務(wù)正常運(yùn)行所必不可少的。
  • @Injectable() 語(yǔ)句特別重要苟弛;它表明此 service 可注入到其他組件中 — 該技術(shù)通常被稱為依賴注入喝滞。
  • 服務(wù)中定義了 3 個(gè)方法,它們的名稱表明了自己的功能膏秫。在方法執(zhí)行時(shí),Angular 將讓瀏覽器訪問網(wǎng)絡(luò)來使用Yahoo提供的服務(wù) API做盅。

我們現(xiàn)在把組件鏈接到所創(chuàng)建的服務(wù)上缤削。
修改 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 服務(wù),如下所示添加以下兩行吹榴,

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 { }

修改組件視圖

現(xiàn)在在HTML視圖中調(diào)用 Shared 服務(wù)的方法亭敢。
修改 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>

完成以上的開發(fā)后,dw-ng2-app 就可以在瀏覽器接受用戶的輸入了远剩。

運(yùn)行應(yīng)用程序

啟動(dòng)應(yīng)用程序扣溺,在瀏覽器里面輸入一些信息,查看結(jié)果瓜晤。例如锥余,在 Weather 頁(yè)面,輸入 San Francisco 來查看該城市的天氣情況:


天氣服務(wù)頁(yè)面

工作正常痢掠,但我們還可以讓 UI 更具吸引力驱犹。改進(jìn) GUI 的一種方法是使用 Bootstrap嘲恍,改進(jìn)以后的頁(yè)面如下,

使用Bootstrap改進(jìn)后的天氣服務(wù)頁(yè)面

結(jié)束語(yǔ)

我們學(xué)習(xí)了如何使用 Angular 2 編寫一個(gè) SPA雄驹,并在開發(fā)計(jì)算機(jī)和沙箱服務(wù)器中運(yùn)行它佃牛。
對(duì)于實(shí)際業(yè)務(wù)需求,可能還需要服務(wù)端的功能支持医舆,來提供如身份驗(yàn)證俘侠、業(yè)務(wù)功能等服務(wù)。這些服務(wù)器端技術(shù)彬向,可以使用 Node.js兼贡,也可以使用 Java、PHP等娃胆。
在應(yīng)用程序性能方面的遍希,可以繼續(xù)關(guān)注和研究以下方面:

  • 捆綁:該進(jìn)程將您的許多程序組合到一個(gè)文件中。
  • 微型化:壓縮捆綁的文件里烦,以便盡可能地減小項(xiàng)目大小凿蒜。
  • 提前 (AoT) 編譯:服務(wù)器復(fù)雜在構(gòu)建過程中提前編譯,而不是瀏覽器在運(yùn)行時(shí)期間執(zhí)行即時(shí) (JIT) 編譯胁黑。

文章導(dǎo)航

  1. 使用 Angular 2 開發(fā)單頁(yè)應(yīng)用程序之一
  2. 使用 Angular 2 開發(fā)單頁(yè)應(yīng)用程序之二
  3. 使用 Angular 2 開發(fā)單頁(yè)應(yīng)用程序之三

進(jìn)一步的學(xué)習(xí)

免費(fèi)獲取項(xiàng)目源代碼废封,咨詢老師進(jìn)行答疑指導(dǎo),請(qǐng)加QQ:1628145742 丧蘸,或報(bào)名我們的實(shí)戰(zhàn)課程:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末漂洋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子力喷,更是在濱河造成了極大的恐慌刽漂,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弟孟,死亡現(xiàn)場(chǎng)離奇詭異贝咙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拂募,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門庭猩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人陈症,你說我怎么就攤上這事蔼水。” “怎么了爬凑?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵徙缴,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)于样,這世上最難降的妖魔是什么疏叨? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮穿剖,結(jié)果婚禮上蚤蔓,老公的妹妹穿的比我還像新娘。我一直安慰自己糊余,他們只是感情好秀又,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贬芥,像睡著了一般吐辙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蘸劈,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天昏苏,我揣著相機(jī)與錄音,去河邊找鬼威沫。 笑死贤惯,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的棒掠。 我是一名探鬼主播孵构,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼烟很!你這毒婦竟也來了颈墅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤雾袱,失蹤者是張志新(化名)和其女友劉穎精盅,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谜酒,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年妻枕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了僻族。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屡谐,死狀恐怖述么,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情愕掏,我是刑警寧澤度秘,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響剑梳,放射性物質(zhì)發(fā)生泄漏唆貌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一垢乙、第九天 我趴在偏房一處隱蔽的房頂上張望锨咙。 院中可真熱鬧,春花似錦追逮、人聲如沸酪刀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)骂倘。三九已至,卻和暖如春巴席,著一層夾襖步出監(jiān)牢的瞬間历涝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工情妖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睬关,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓毡证,卻偏偏與公主長(zhǎng)得像电爹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子料睛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容