在昨天我们建立了 Angular 专案、使用 JSON-server 来制作 mock db,并且建立了英雄资料。今天这篇文章我们将完成下列事项:
(现在,我们要试着召唤英灵...)
我知道!再怎麽说,我也是个读书人呢。
(哦?你知道什麽?)
要召唤英灵对吧,那就要念这个咒文——「速速前吕布奉先!」。
(呃...)
我知道问题出在哪了。速速前只能召唤物体,所以,我要召唤方天画戟,这样拿着方天画戟的吕布就会一起传过来——「速速前方天画戟!」。
(神啊,我是不是做错了什麽。)
糟糕,难道是因为我没有梦见妈祖吗......
(你最好什麽都不要念,好好看接下来的文章。)
现在,我们在 mock db 里面存有英雄资料,透过 JSON-server 的协助,可以在 Angular 中来模拟使用 http 来呼叫 api 的行为。在 Angular 中,我们可以引入 HttpClientModule,并使用这个模组所拥有的提供商(provider)HttpClient, 来执行 http 请求。
在引入 HttpClientModule 模组之前,要先简单说明「模组」(module)概念。「模组」概念解决的问题是,将应用程序更有组织地进行管理,而透过 import、export,就可以很好地达到复用程序码的目的,在 JavaScript ES6 版本中,正式提出了模组系统 ,也就是「JS 模组」。
而在 Angular 中,模组化包含了两个部分 :
@NgModule
装饰器标记的类别,在装饰器里面会放置元资料的物件,你也需要在这个物件中说明「宣告」(declarations)、「汇入」(imports)、「汇出」(exports)...分别有哪些类别。我们可以先用「佣兵团」概念来思考 @NgModule
装饰器记载的元资料:
「佣兵团」概念或许可以说明在 NgModule 使用其他 NgModule 提供的支援服务,但这个概念也存在一个风险:那就是「支援协定并不是双向的,而是单方面寻求支援」。意思是,你不能在 A 模组汇入 B 模组的情形下,同时在 B 模组汇入 A 模组,这会造成循环汇入的错误
。对这个风险有印象,在日後遇到时,你就会知道发生了什麽事情,应该从何着手处理。
现在让我们看看专案中必定存在的根模组 AppModule(app.module.ts):
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
上方的 import {xxx} from 'path';
即为汇入 JS 模组的语法。而 @NgModule 里面的各种阵列,即为此模组的相关内容。先看「宣告」(declarations) 阵列,这里是放置宣告隶属这个 module 档案中的类别,现在这里拥有 AppComponent 元件,如下:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'angular-tour-of-heroes';
}
可以看到,AppComponent 是一个带有 @Component
(元件)装饰器的类别。你可以这麽想,带有 @Component
(元件) 、 @Directive
(指令) 、@Pipe
(管道) 装饰器的类别,就是通过认证的佣兵。不同的装饰器,用来说明佣兵负责的不同功用。
并且,在这个世界中不存在个体户佣兵,所有想要从事佣兵工作的人,都必须加入佣兵团,也只能加入一个佣兵团。具体来说,AppComponent 只能登记在一个 NgModule 的「宣告」(declarations)中,无法再宣吿在其他 NgModule 下;如果没有宣告在任何 NgModule 中,就没有人可以使用 AppComponent。
此外,关於带有元件/指令/管道不同装饰器的类别,我们慢慢都会使用到。
现在,在根模组 AppModule 「汇入」(imports)阵列中加入 HttpClientModule【与其他佣兵团签订支援协议
】,让我们可以使用 HttpClientModule 汇出(exports)的内容【使用其他佣兵团有提供支援服务的佣兵
】。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Angular 就是一个 JavsScript 框架,连 NgModule
装饰器,都是作为 JS 模组汇入到需要使用的地方的。
更详尽的说明,请参考官方文件。
为了更好的演示,让我们用 Angular CLI 来建立一个 hero-list
元件。进入 src/app 目录,这里有个小技巧,在编辑器中,我们可以针对想要建立元件的资料夹点击滑鼠右键,就可以发现「在终端机中打开」(Open in Integrated Terminal),点击它,编辑器就会为我们打开终端机,并预设在此路径中。
接着就可以执行下列指令:
ng g c hero-list // g for generate, c for component
Anglaur CLI 就会建立数个档案,可能包含「.html」、「.ts」、「.css」、「.spec.ts」,并同时更新了 app.module.ts
,让我们查看更新的档案:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { HeroListComponent } from './hero-list/hero-list.component';
@NgModule({
declarations: [
AppComponent,
HeroListComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
可以发现,Angualr CLI 帮我们在这个模组中宣告了 HeroListComponent 类别,因此,我们就可以在这个模组中使用它——以这里来说,我们就可以在 AppComponent 中使用 HeroListComponent。
因为在 app.module.ts
中汇入了 HttpClientModule
模组,我们就可以在宣告在 app.module.ts
的 HeroListComponent 里,使用 HttpClientModule
汇出的内容,包括 HttpClient。
打开 hero-list.component.ts 档案,在建构式(constructor)中注入 HttpClient:
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
styleUrls: ['./hero-list.component.css']
})
export class HeroListComponent implements OnInit {
constructor(
private http: HttpClient
) { }
ngOnInit(): void {
}
}
然後我们使用它来取得英雄资料,在 ngOnInit 里撰写相关程序码:
constructor(
private http: HttpClient
) { }
ngOnInit(): void {
this.http.get('api/heros').subscribe((heroList) => {
console.log('HeroList', heroList);
});
}
如果现在用浏览器打开此 App,console 是不会印出 HeroList 的,因为我们根本还没在 app 中使用 HeroListComponent 元件。
要怎麽使用元件呢?在 hero-list.component.ts
的 @Component 装饰器
里的元资料物件有个属性 selector: 'app-hedo-list',这个就是我们可以写在 *.html 档案中、代表使用此元件的语法,类似 HTML 的 tag。
让我们在根元件 app.component.html
中使用 HeroListComponent 元件:
<app-hero-list></app-hero-list>
如此我们就可以在 app 中看到如下画面,代表我们确实取得了英雄资料:
小提醒:当你新增/删除档案後,必须重启专案(ng serve
)才会执行改变後的程序码。
<<: Day 4 - [Zenbo开发系列] 01-後盖打开方式、侦错USB孔位置
>>: 【Day 03】又是 Print Spooler 搞的鬼 - CVE-2021-1675 PrintNightmare
铁人赛最後一天! 今天要跟各位分享的呢,是昨天与前天 Banana in a box 系列的延伸,关...
昨天我们讲了在numpy中NaN要如何判断相等 那今天就来稍微谈一下会出现缺失值的那些情况要怎麽处理...
urls.py str有可以用int path('personal_info<str:name...
猫咪跑步 ( 超长背景 ) 教学原文参考:猫咪跑步 ( 超长背景 ) 这篇文章会介绍,如何在 Scr...
搞定 Mac 的软件和终端机,接下来要学习一步步把其他工具的使用环境建立起来,并学习如何去运用。 1...