Angular学习教程-英雄之旅

本文档详细介绍了如何使用Angular进行项目创建、组件制作、服务添加、路由设置以及HTTP服务的使用,通过一步步操作,最终构建出一个英雄编辑器,包括英雄列表、详情编辑、主从组件、消息服务和应用内导航等功能。同时,教程还涵盖了错误处理和数据的获取与操作,如添加、删除和搜索英雄。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Angular学习教程-英雄之旅

官网链接

https://angular.cn/tutorial

文章目录

一、能学习到

在本教程的最后,将完成下列工作:

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

二、创建项目

ng new heroes --skip-install

image-20201231140800990

cd heroes

npm set registry https://registry.npmjs.org/

npm cache clean --force

npm install

image-20201231141229874

  • 启动应用服务器

ng serve --open

image-20201231141409581

  • 让整个应用保持一致的外观。

在src/styles.css (excerpt)下添加

/* Application-wide Styles */
h1 {
    color: #369;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 250%;
  }
  h2, h3 {
    color: #444;
    font-family: Arial, Helvetica, sans-serif;
    font-weight: lighter;
  }
  body {
    margin: 2em;
  }
  body, input[type="text"], button {
    color: #333;
    font-family: Cambria, Georgia;
  }
  /* everywhere else */
  * {
    font-family: Arial, Helvetica, sans-serif;
  }

三、英雄编辑器

Part1

1.创建英雄列表组件
  • ng generate component heroes

CLI 创建了一个新的文件夹 src/app/heroes/,并生成了 HeroesComponent 的四个文件。

app/heroes/heroes.component.ts

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

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.scss']
})
export class HeroesComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

CLI 自动生成了三个元数据属性:

  1. selector— 组件的选择器(CSS 元素选择器)
  2. templateUrl— 组件模板文件的位置。
  3. styleUrls— 组件私有 CSS 样式表文件的位置。
2.添加 hero 属性

heroes.component.ts

export class HeroesComponent implements OnInit {
   
  hero = 'Windstorm';

  constructor() {
    }

  ngOnInit(): void {
   
  }

}
4.显示英雄

heroes.component.html

{
  {hero}}

src/app/app.component.html

<h1>1</h1>
<h1>{
  {title}}</h1>
<app-heroes></app-heroes>
5.启动

image-20201231143703338

Part2

1.创建Hero类

新建文件src/app/hero.ts

export interface Hero {
   
    id: number;
    name: string;
  }
2.把组件的 hero 属性的类型重构为 Hero

src/app/heroes/heroes.component.ts

import {
    Component, OnInit } from '@angular/core';
import {
    Hero } from '../hero'

@Component({
   
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.scss']
})
export class HeroesComponent implements OnInit {
   
  hero: Hero = {
   
    id: 1222,
    name: 'Windstorm'
  };
  constructor() {
    }

  ngOnInit(): void {
   
  }

}

3.显示 hero 对象

修改模板中的绑定,以显示英雄的名字

src/app/heroes/heroes.component.html

<!-- uppercase把文本转换成全大写形式。 -->
<h2>{
  { hero.name | uppercase}} Details</h2>
<div><span>id: </span>{
  {hero.id}}</div>
<div><span>name: </span>{
  {hero.name}}</div>

  • 绑定表达式中的 uppercase 位于管道操作符( | )的右边,用来调用内置管道 UppercasePipe

  • 管道 是格式化字符串、金额、日期和其它显示数据的好办法。

4.双向绑定

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

src/app/heroes/heroes.component.html

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

<!-- uppercase把文本转换成全大写形式。 -->
<h2>{
  { hero.name | uppercase}} Details</h2>
<div><span>id: </span>{
  {hero.id}}</div>
<div><span>name: </span>{
  {hero.name}}</div>

  • [(ngModel)] 是 Angular 的双向数据绑定语法。

  • 这里把 hero.name 属性绑定到了 HTML 的 textbox 元素上,以便数据流可以双向流动:从 hero.name 属性流动到 textbox,并且从 textbox 流回到 hero.name

5.缺少 FormsModule

发现报错

  • 导入 FormsModule

app.module.ts

import {
    NgModule } from '@angular/core';
  • 然后把 FormsModule 添加到 @NgModule 元数据的 imports 数组中,这里是该应用所需外部模块的列表。
imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule
  ],

最后结果

输入框和其他hero.name完成双向绑定

image-20201231150249727

四、显示英雄列表

Part1

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

创建一些模拟的英雄数据,并假装它们是从服务器上取到的。

src/app/mock-heroes.ts

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' }
];
2.显示这些英雄

src/app/heroes/heroes.component.ts

打开 HeroesComponent 类文件,并导入模拟的 HEROES

import {
    HEROES } from '../mock-heroes';

往类中添加一个 heroes 属性,这样可以暴露出这个 HEROES 数组,以供绑定。

export class HeroesComponent implements OnInit {
   
  heroes = HEROES;
  //...
  }
3.使用 *ngFor 列出这些英雄

heroes.component.html

<h2>My Heroes</h2>
<ul class="heroes">
    <li *ngFor="let hero of heroes">
    <span class="badge">{
  {hero.id}}</span> {
  {hero.name}}
  </li>
</ul>
	
  • <li> 就是 *ngFor 的宿主元素。
  • heroes 就是来自 HeroesComponent 类的列表。
  • 当依次遍历这个列表时,hero 会为每个迭代保存当前的英雄对象。
4.可能会遇到的错误
  • 意思是不能读取到mock-heroes.ts

image-20201231152745178

  • 解决方法
  • 在tsconfig.app.json的files或include下添加这句话

“src/app/mock-heroes.ts”

image-20201231152928811

  • 本人添加后可以运行
  • 运行后注释后也可运行(有点莫名其妙)
  • 可能是include下的"src/**/*.d.ts"本来就可以读取到mock-heroes.ts文件,但是一开始没有读取成功。
4.效果如下

image-20201231153409421

Part2

1.给英雄列表“美容”

src/app/heroes/heroes.component.css

/* HeroesComponent's private CSS styles */
.heroes {
    margin: 0 0 2em 0;
    list-style-type: none;
    padding: 0;
    width: 15em;
  }
  .heroes li {
    cursor: pointer;
    position: relative;
    left: 0;
    background-color: #EEE;
    margin: .5em;
    padding: .3em 0;
    height: 1.6em;
    border-radius: 4px;
  }
  .heroes li:hover {
    color: #607D8B;
    background-color: #DDD;
    left: .1em;
  }
  .heroes li.selected {
    background-color: #CFD8DC;
    color: white;
  }
  .heroes li.selected:hover {
    background-color: #BBD8DC;
    color: white;
  }
  .heroes .badge {
    display: inline-block;
    font-size: small;
    color: white;
    padding: 0.8em 0.7em 0 0.7em;
    background-color:#405061;
    line-height: 1em;
    position: relative;
    left: -1px;
    top: -4px;
    height: 1.8em;
    margin-right: .8em;
    border-radius: 4px 0 0 4px;
  }
2.主从结构

当用户在列表中点击一个英雄时,该组件应该在页面底部显示所选英雄的详情

在本节,你将监听英雄条目的点击事件,并更新英雄的详情。

①添加 click 事件绑定

src/app/heroes/heroes.component.html

<li *ngFor="let hero of heroes" (click)="onSelect(hero)">
②添加 click 事件处理器

src/app/heroes/heroes.component.ts

selectedHero: Hero| undefined;
onSelect(hero: Hero): void {
   
  this.selectedHero = hero;
}
③添加详情区

heroes.component.html 中该列表的紧下方,添加如下代码:

src/app/heroes/heroes.component.html

<!-- 详情区 -->
<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>

[class.selected]="hero === selectedHero"给所有的英雄添加样式。

效果展示

image-20201231160033674

五、主从组件

此刻,HeroesComponent 同时显示了英雄列表和所选英雄的详情。

把所有特性都放在同一个组件中,将会使应用“长大”后变得不可维护。 你要把大型组件拆分成小一点的子组件,每个子组件都要集中精力处理某个特定的任务或工作流。

本页面中,你将迈出第一步 —— 把英雄详情移入一个独立的、可复用的 HeroDetailComponent

1.制作 HeroDetailComponent

ng generate component hero-detail

①编写模板

src/app/hero-detail/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>
②添加 @Input() hero 属性

src/app/hero-detail/hero-detail.component.ts

import {
    Hero } from '../hero';

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

src/app/hero-detail/hero-detail.component.ts

import {
    Component, OnInit, Input } from '@angular/core';
@Input() hero: Hero;
③修改 HeroesComponent 的模板

app/heroes/heroes.component.html

<app-hero-detail [hero]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值