Angular2官网项目 第三天

为了不再把相同的代码复制一遍又一遍,我们要创建一个单一的可复用的数据服务,并且把它注入到需要它的那些组件中。 使用单独的服务可以保持组件精简,使其集中精力为视图提供支持,并且,借助模拟(Mock)服务,可以更容易的对组件进行单元测试。

由于数据服务总是异步的,因此我们最终会提供一个基于承诺(Promise)的数据服务

一:创建英雄服务

客户向我们描绘了本应用更大的目标:想要在不同的页面中用多种方式显示英雄。 现在我们已经能从列表中选择一个英雄了,但这还不够。 很快,我们将添加一个仪表盘来显示表现最好的英雄,并创建一个独立视图来编辑英雄的详情。 所有这些视图都需要英雄数据。

目前,AppComponent显示的是模拟数据。 不过,定义这些英雄并非组件的任务,否则我们没法与其它组件和视图共享这些英雄列表数据。 在这一章,我们将把获取英雄数据的任务重构为一个单独的服务,它将提供英雄数据,并把服务在所有需要英雄数据的组件间共享。

创建GeneralService

在./app目录下创建general.service.ts

注意:

我们遵循的文件命名约定是:服务名称的小写形式(基本名),加上.service后缀。 如果服务名称包含多个单词,我们就把基本名部分写成中线形式 (dash-case)。 例如,SpecialSuperHeroService服务应该被定义在special-super-hero.service.ts文件中。

我们把这个类命名为GeneralService,并导出它,以供别人使用。

./app/general.service.ts

import { Injectable } from ‘@angular/core‘;

@Injectable()

export class GeneralService{

}

可注入的服务

注意,我们导入了 Angular 的Injectable函数,并作为@Injectable()装饰器使用这个函数。

注意:不要忘了写圆括号!如果忘了写,就会导致一个很难诊断的错误。

当 TypeScript 看到@Injectable()装饰器时,就会记下本服务的元数据。 如果 Angular 需要往这个服务中注入其它依赖,就会使用这些元数据。

获取英雄数据

添加一个名叫getGenerals的桩方法。

@Injectable()

export class GeneralService{

getGenerals():void{

};

}

重要:GeneralService可以从任何地方获取Genera数据 —— Web服务、本地存储或模拟数据源。 从组件中移除数据访问逻辑意味着你可以随时更改这些实现方式,而不影响需要这些英雄数据的组件

返回模拟的英雄数据

.app/general.service.ts

import { Injectable } from ‘@angular/core‘;

import {General} from ‘../bean/General‘;

import {Generals} from "../data/mock-general";

@Injectable()

export class GeneralService{

getGenerals():General[]{

return Generals;

};

}

导入GeneralService

.app/app.component.ts

import {GeneralService} from‘./general.service‘;

注入 GeneralService

步骤

  • 添加一个构造函数,并定义一个私有属性。

.app/app.component.ts

constructor(private generalService:GeneralService ){

}

构造函数自己什么也不用做,它在参数中定义了一个私有的generalService属性,并把它标记为注入generalService的靶点。

现在,当创建AppComponent实例时,Angular 知道需要先提供一个generalService的实例。

  • 添加组件的providers元数据。

我们还得注册一个HeroService提供商,来告诉注入器如何创建HeroService。 要做到这一点,我们在@Component组件的元数据底部添加providers数组属性如下

.app/app.module.ts

import {GeneralService} from‘./general.service‘;

providers: [GeneralService],

providers数组告诉 Angular,当它创建新的AppComponent组件时,也要创建一个GeneralService的新实例。 AppComponent会使用那个服务来获取英雄列表,在它组件树中的每一个子组件也同样如此。

AppComponent 中的 getHeroes()

该服务被存入了一个私有变量generalService中。

我们可以在用一个方法调用此服务,并获得数据

getGenerals():void{

this.generals=this.generalService.getGenerals();

}

ngOnInit 生命周期钩子

毫无疑问,AppComponent应该获取英雄数据并显示它。

你可能想在构造函数中调用getGenerals()方法,但构造函数不应该包含复杂的逻辑,特别是那些需要从服务器获取数据的逻辑更是如此。构造函数是为了简单的初始化工作而设计的,例如把构造函数的参数赋值给属性。

只要我们实现了 Angular 的 ngOnInit 生命周期钩子,Angular 就会主动调用这个钩子。 Angular提供了一些接口,用来介入组件生命周期的几个关键时间点:刚创建时、每次变化时,以及最终被销毁时。

每个接口都有唯一的一个方法。只要组件实现了这个方法,Angular 就会在合适的时机调用它。

这是OnInit接口的基本轮廓(但不要拷贝到你自己的代码中):

import { OnInit } from ‘@angular/core‘;export class AppComponent implements OnInit {
 ngOnInit(): void {
 }}

我们写了一个带有初始化逻辑的ngOnInit方法,Angular会在适当的时候调用它。 在这个例子中,我们通过调用getGenerals()来完成初始化。

ngOnInit(){

this.getGenerals();

}

我们的应用将会像期望的那样运行,显示英雄列表,并且在我们点击英雄的名字时,显示英雄的详情。

异步服务与承诺

我们的generalService立即返回一个模拟的英雄列表,它的getGenerals()函数签名是同步的。

问题:

但最终,英雄的数据会从远端服务器获取。当使用远端服务器时,用户不会等待服务器的响应。换句话说,你没法在等待期间阻塞浏览器界面。

为了协调视图与响应,我们可以使用承诺(Promise),它是一种异步技术,它会改变getGenerals()方法的签名。

Promise具体介绍 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

       GeneralService会生成一个承诺

承诺 它就是一个承诺,在有了结果时,它承诺会回调我们。 我们请求一个异步服务去做点什么,并且给它一个回调函数。 它会去做(在某个地方),一旦完成,它就会调用我们的回调函数,并通过参数把工作结果或者错误信息传给我们。


    GeneralServicegetGenerals方法改写为返回承诺的形式:

基于承诺的行动

修改GeneralService之后,this.generals会被赋值为一个Promise而不再是英雄数组。

getGenerals():void{

this.generals=this.generalService.getGenerals();

}

我们得修改这个实现,把它变成基于承诺的,并在承诺的事情被解决时再行动。 一旦承诺的事情被成功解决(Resolve),我们就会显示英雄数据。

我们把回调函数作为参数传给承诺对象的then方法:

getGenerals():void{

this.generalService.getGenerals()

.then(generals=>this.generals=generals);

}

在回调函数中,我们把服务返回的英雄数组赋值给组件的generals属性。

我们的程序仍在运行,仍在显示英雄列表,在选择英雄时,仍然会把它/她显示在详情页面中。

.app/general.service.ts

import { Injectable } from ‘@angular/core‘;

import {General} from ‘../bean/General‘;

import {Generals} from "../data/mock-general";

@Injectable()

export class GeneralService{

getGenerals():Promise<General[]>{

return Promise.resolve(Generals);

};

}

.app/app.component.ts

import { Component,OnInit} from ‘@angular/core‘;

import {General}  from "../bean/General";

import {GeneralService} from‘./general.service‘;

@Component({

selector: ‘app-root‘,

templateUrl: ‘./app.component.html‘,

styleUrls: [‘./app.component.scss‘]

})

export class AppComponent implements OnInit {

title = ‘MY General‘;

// generals:General[]=Generals;

constructor(private generalService:GeneralService ){

}

selectGeneral:General;

generals:General[];

getGenerals():void{

this.generalService.getGenerals()

.then(generals=>this.generals=generals);

}

ngOnInit(){

this.getGenerals();

}

oSelect(item:General):void{

this.selectGeneral=item;

}

}

时间: 2024-08-24 05:50:19

Angular2官网项目 第三天的相关文章

Angular2官网项目 第一天

来自官网: 这篇<英雄指南>涵盖`了 Angular 的核心原理.这次构建的应用会涉及很多特性:获得并显示英雄列表,编辑所选英雄的详情,并在英雄数据的多个视图之间建立导航.这些特性,在成熟的.数据驱动的应用中经常见到. 完成本教程后,我们将学习足够的 Angular 核心技术,并确信 Angular 确实能做到我们需要它做的. 我们将涵盖大量入门级知识,同时我们也会看到大量链接,指向更深入的章节. 一 :为本地开发搭建环境 a.检查@angular/cli版本. 在命令行输入 ng -v  -

Angular2官网项目 (4)--路由

        完整项目地址:https://github.com/lixinsong123/heroGuide 行动计划      把AppComponent变成应用程序的"壳",它只'处理导航' 把现在由AppComponent关注的英雄们移到一个独立的GeneralComponent中 添加路由 创建一个新的DashboardComponent组件 把仪表盘加入导航结构中 路由是导航的另一个名字.路由器就是从一个视图导航到另一个视图的机制. 拆分Appcomponent.    

Angular2官网项目 第二天

接着昨天的来 给我们的英雄们"美容" 重构.app/app.component.scss .container{ h1{ text-align: center; color: red; } .row{ line-height: 30px; padding: 10px 0; label{ text-align: right; } } .controller{ padding:0 360px; li{ height: 50px; } label{ @extend %link; text-a

谈谈Python之Django搭建企业级官网(第三篇下部)

转载请注明来源地址和原作者(CFishHome) 前沿 上一篇文章我们学习了URL与视图函数的映射.传递参数的三种方式.转换器的简单使用和include函数分层映射管理.接下来这一篇文章着重介绍Path.re_path.include.reverse.redirect函数的使用和自定义URL转换器.学完这些内容,相信我们对URL和视图都会有了一定的了解和认识.为了让每篇文章具有一定的独立性,我决定每篇文章都重新新建一个项目,便于测试和调试. 预备 首先,我们在Pycharm重新新建一个名为boo

记一次失败的官网项目

唉,二十多天没写文章了,最近忙的头皮发麻,五一都不放假加班,五一劳动节,你们过得是劳动节中的节日,我过得是劳动节的劳动,惨啊 大家看到文章标题可能会好奇,官网不是很简单吗?咋就失败了,别急,听我娓娓道来 第一幕(被睡服的我) 记得那是一个阳光不怎么明媚并且代码又出了bug的下午 (孙子给您来电话了,孙子给你来电话了) 帅气的我:喂,您好! 未知人物:哎,XX,我啊,剑哥(我的大学老师,技术很厉害人也很温和正是在他的影响下我才越来越喜欢代码) 帅气的我:哎,啥事啊剑哥 剑哥:我这边有何朋友要做公司

angular2自学笔记---官网项目(一)

1.单向数据绑定的'插值表达式' angular中最典型的数据显示方式:把HTML模板(template)的控件绑定到angular组件的属性(component相当于一个构造函数,下面例子中的这个构造函数有name.title.和hero三个属性)简单来说就是把组件的属性名放到显示曾{{属性名}}中,angular负责喷到页面中:angular从组件中提取属性插入浏览器,然后angular会自动监听这些属性值的变化,一旦属性值发生变化,angular会自动刷新显示,这里的刷新,严格意义上指的是

谈谈Python之Django搭建企业级官网(第三篇上部)

转载请注明来源地址和原作者(CFishHome) 前沿 上一节的学前准备工作和第一个小牛试刀的Django项目学习,让我们对Django开发越来越感兴趣了.正所谓趁热打铁,让我们继续来学习网站开发必备的视图函数和URL映射等知识,跟着步伐一起学习,我相信你会收获很多.噔~噔,新闻播报时间:9月12-9月16有两个超强台风在广东湛江登陆,沿途影响众多城市,包括深圳!!所以很遗憾,前几天打算和舍友去深圳游玩的计划泡汤了,也只能推迟几天前往深圳度中秋.看月亮了~ DEBUG模式 无论是使用命令行还是P

Nginx官网提供的版本类型

Nginx官网提供了三个类型的版本Mainline version:Mainline 是 Nginx 目前主力在做的版本,可以说是开发版Stable version:最新稳定版,生产环境上建议使用的版本Legacy versions:遗留的老版本的稳定版

angular2使用官网npm install下载依赖失败的处理方法

上一两个月在学习angular2,在下载依赖阶段看官网是直接自动下载的,[npm install] 就能把依赖全部弄下来.不过作为新手的我,是倒腾来倒腾去都倒不出来,因为老是报同一个错.官网也还有手动下载的,[npm run typings install],不过这个命令是报了另外一个错. 不过上面说到倒腾,其实倒腾也是有时候被你倒腾着的时候,没错,我就是倒腾的时候发现能够下载了,真神器. 这里就跟大家分享下目前来说,用 [npm]命令怎么弄依赖下来的. 这句话很重要[先手动,接着自动] (重要