Angular官方文档学习-英雄之旅

Angular教程-英雄之旅

本教程需要完成的工作:

  • 使用 Angular 的内置指令来显示 / 隐藏元素,并显示英雄数据的列表。
  • 创建 Angular 组件以显示英雄的详情,并显示一个英雄数组。
  • 为只读数据使用单向数据绑定
  • 添加可编辑字段,使用双向数据绑定来更新模型。
  • 把组件中的方法绑定到用户事件上,比如按键和点击。
  • 让用户可以在主列表中选择一个英雄,然后在详情视图中编辑他。
  • 使用管道来格式化数据。
  • 创建共享的服务来管理这些英雄。
  • 使用路由在不同的视图及其组件之间导航。

编辑英雄名字

用户应该能在一个 <input> 输入框中编辑英雄的名字。

当用户输入时,这个输入框应该能同时显示修改英雄的 name 属性。 也就是说,数据流从组件类流出到屏幕,并且从屏幕流回到组件类

要想让这种数据流动自动化,就要在表单元素 <input> 和组件的 hero.name 属性之间建立双向数据绑定。

双向绑定

把模板中的英雄详情区重构成这样:

<div>
    <label>name:
        <input [(ngModel)]="hero.name" placeholder="name"/>
    </label>
</div>

ngModel 是一个有效的 Angular 指令,不过在默认情况下是不可用的。

它属于一个可选模块 FormsModule,必须自行添加此模块才能使用该指令

import {
    FormsModule } from '@angular/forms';
//在NgModule中
imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
  ],

注意:每个组件都必须声明在(且只能声明在)一个NgModule中。

显示英雄列表

创建模拟(mock)的英雄数据

import {
    Hero } from './hero';

export const HEROES: Hero[] = [
  {
    id: 11, name: 'Dr Nice' },
  {
    id: 12, name: 'Narco' },
  {
    id: 13, name: 'Bombasto' },
  {
    id: 14, name: 'Celeritas' },
  {
    id: 15, name: 'Magneta' },
  {
    id: 16, name: 'RubberMan' },
  {
    id: 17, name: 'Dynama' },
  {
    id: 18, name: 'Dr IQ' },
  {
    id: 19, name: 'Magma' },
  {
    id: 20, name: 'Tornado' }
];

@Component 元数据中指定的样式和样式表都是局限于该组件的。 heroes.component.css 中的样式只会作用于 HeroesComponent,既不会影响到组件外的 HTML,也不会影响到其它组件中的 HTML。

*ngFor是一个 Angular 的复写器(repeater)指令。 它会为列表中的每项数据复写它的宿主元素。

<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)">
<!-- click 外面的圆括号会让 Angular 监听这个 <li> 元素的 click 事件。 当用户点击 <li> 时,Angular 就会执行表达式 onSelect(hero)。 -->
    <span class="badge">{
  {hero.id}}</span> {
  {hero.name}}
  </li>
</ul>
<div *ngIf="selectedHero">

    <h2>{
  {selectedHero.name | uppercase}} Details</h2>
    <div><span>id: </span>{
  {selectedHero.id}}</div>
    <div>
      <label>name:
        <input [(ngModel)]="selectedHero.name" placeholder="name"/>
      </label>
    </div>
  
  </div>

下面的写法是错误的:

原因:当应用启动时,selectedHeroundefined,但模板中的绑定表达式引用了 selectedHero 的属性(表达式为 { {selectedHero.name}}),这必然会失败,因为还没选过英雄。

正确的写法是使用*ngFor隐藏,该组件只有当元素存在时才会显示

原理:当 selectedHeroundefined 时,ngIf 从 DOM 中移除了英雄详情。因此也就不用关心 selectedHero 的绑定了。当用户选择一个英雄时,selectedHero 也就有了值,并且 ngIf 把英雄的详情放回到 DOM 中。

<h2>{
  {selectedHero.name | uppercase}} Details</h2>
<div><span>id: </span>{
  {selectedHero.id}}</div>
<div>
  <label>name:
    <input [(ngModel)]="selectedHero.name" placeholder="name"/>
  </label>
</div>

Angular 的 CSS类绑定机制机制让根据条件添加或移除一个 CSS 类变得很容易。 只要把 [class.some-css-class]="some-condition" 添加到你要施加样式的元素上就可以了。

把英雄详情移入一个独立的、可复用的组件。

<!--hero-detail.component.html-->
<div *ngIf="hero">

  <h2>{
  {hero.name | uppercase}} Details</h2>
  <div><span>id: </span>{
  {hero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="hero.name" placeholder="name"/>
    </label>
  </div>

</div>

HeroDetailComponent 模板中绑定了组件中的 hero 属性,它的类型是 Hero。将Hero符号导入。

hero 属性必须是一个带有@Input()装饰器的输入属性,因为外部的 HeroesComponent 组件将会绑定到它。

<!--hero.component.html-->
<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes"
    [class.selected]="hero === selectedHero"
    (click)="onSelect(hero)">
    <span class="badge">{
  {hero.id}}</span> {
  {hero.name}}
  </li>
</ul>
<!--hero组件的html,在其中调用了绑定了detail组件-->
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
<!--[hero]="selectedHero" 是 Angular 的属性绑定语法。
这是一种单向数据绑定。从 HeroesComponent 的 selectedHero 属性绑定到目标元素的 hero 属性,并映射到了 HeroDetailComponent 的 hero 属性。-->

image-20201231145616954

服务

为什么需要服务

组件不应该直接获取或保存数据,它们不应该了解是否在展示假数据。 它们应该聚焦于展示数据,而把数据访问的职责委托给某个服务。

@Injectable() 服务

注意,这个新的服务导入了 Angular 的 Injectable 符号,并且给这个服务类添加了 @Injectable() 装饰器。 它把这个类标记为依赖注入系统的参与者之一。HeroService 类将会提供一个可注入的服务,并且它还可以拥有自己的待注入的依赖。 目前它还没有依赖,但是[很快就会有了。

@Injectable() 装饰器会接受该服务的元数据对象,就像 @Component() 对组件类的作用一样。

获取英雄数据

HeroService 可以从任何地方获取数据:Web 服务、本地存储(LocalStorage)或一个模拟的数据源。

提供(provide) HeroService

必须先注册一个服务提供者,来让 HeroService 在依赖注入系统中可用,Angular 才能把它注入到 HeroesComponent 中。所谓服务提供者就是某种可用来创建或交付一个服务的东西;在这里,它通过实例化 HeroService 类,来提供该服务。

为了确保 HeroService 可以提供该服务,就要使用注入器来注册它。注入器是一个对象,负责当应用要求获取它的实例时选择和注入该提供者。

默认情况下,Angular CLI 命令 ng generate service 会通过给 @Injectable() 装饰器添加 providedIn: 'root' 元数据的形式,用根注入器将你的服务注册成为提供者。

<!--hero.service.ts-->
import {
    Injectable } from '@angular/core';
import {
   Hero} from './hero';
import {
   HEROES} from './mock-heroes';
@Injectable({
   
  providedIn: 'root'
})
export class HeroService {
   

  constructor() {
    }
  getHeroes(): Hero[] {
   
    return HEROES;
  }
}

HeroesCompoent导入服务<

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值