Angular 开发学习 04 – 组件和模块

栏目: JavaScript · 发布时间: 6年前

内容简介:获取本章的源代码,可以使用我们从最开始的这个命令是使用 Angular CLI 创建 Angular 项目的语句。它的运行结果是生成一个完整的 Angular 项目开发框架。对于简单的应用,我们完全不需要考虑 webpack 的配置、 测试服务器的热部署等环境搭建的细节,就可以得到一个完善的开发环境。项目创建语句还可以有很多参数,比如,我们想使用 SCSS 而不是原始的 CSS,那么就可以使用下面的语句:

获取本章的源代码,可以使用 git clone https://gitee.com/devbean/learning-angular-todomvc.git ,然后检出 cp04 标签: git checkout cp04 即可。

我们从最开始的 ng new todomvc 开始说起。

这个命令是使用 Angular CLI 创建 Angular 项目的语句。它的运行结果是生成一个完整的 Angular 项目开发框架。对于简单的应用,我们完全不需要考虑 webpack 的配置、 测试服务器的热部署等环境搭建的细节,就可以得到一个完善的开发环境。项目创建语句还可以有很多参数,比如,我们想使用 SCSS 而不是原始的 CSS,那么就可以使用下面的语句:

ng new todomvc --style=scss

这样,我们基本零配置就可以在开发时使用 SCSS。不过为简单起见,我们暂时不会使用 SCSS,而是直接使用 CSS 作为 TodoMVC 的样式表语言。

正如前面的章节说过的那样,使用 ng serve 成功之后即可打开浏览器查看页面的显示。而我们也是介绍过, ng new 命令到底生成了什么。

下面,我们从 src 中的 app 文件夹开始。app 文件夹是所有项目源代码文件所在地。以后的 ng 命令为我们生成的所有文件都会在这个文件夹中。这也是我们主要关心的文件夹之一。

刚刚通过 ng new 命令获得的 app 文件夹中有五个文件:

  • app.component.css
  • app.component.html
  • app.component.ts
  • app.component.spec.ts
  • app.module.ts

可以看到,这五个文件分为两类,分别为 component 和 module。

这种命名方式是 Angular CLI 推荐的。文件名分为三部分:第一部分是文件的名字,第二部分是文件的类型,第三部分是文件的后缀名。例如,app.component.css,这个文件隶属于 app,这个 app 是一个 component,这个文件后缀名是 css。

同时还可以看出,一种类型的文件可能包含多个文件。例如这里的 component 就包含了四个文件。我们会在后面详细介绍这四个文件。

component 和 module 是 Angular 中两类最重要的类型。顾名思义,component 即 组件 ,module 即 模块 。二者的关系是,组件必然隶属于一个模块,一个模块可以包含多个组件。

与 React 或者 Vue 类似,Angular 把页面上所有的元素都看作组件。一个组件可以看作是一段可复用的 HTML 代码片段。在我们做 Java 或者 C++ 开发中,一段可复用的代码通常会抽象为一个函数。函数可以被其它函数调用。在 Angular 中也是类似,一段 HTML 代码片段也可能被复用,例如下面的代码:

<div class="portlet">
	<div class="portlet-header">
		Header
	</div>
	<div class="portlet-body">
		...
	</div>
</div>

这段代码是一个带有标题的 portlet 区域,大致类似下面的样式:

Angular 开发学习 04 – 组件和模块

这段 HTML 代码,连同为表现其样式所附加的 CSS,甚至还有其行为的 JavaScript,放在一起即可被另外的页面复用。那么,我们就可以把这些代码放在一起,抽象为一个组件。在使用 Angular 开发页面时,很多时候都是在把页面分解成为一个个独立的组件,最终将这个组件项目组合起来,完成最终页面的开发。

在 Angular 中,每一个组件都必须属于一个模块。可以认为模块是组件的集合(事实上,模块不仅仅包含组件,还可以有其它内容)。同一模块中的组件可以直接相互使用;不同模块中的组件在相互使用时,需要导入组件所在模块。也就是说,如果你想要使用别人提供的组件,应该引入该组件所在的模块,而不是组件本身。这暗示着,模块其实是 Angular 最基本的部件,因为 Angular 的项目是通过相互引用模块,错综复杂地耦合在一起。

在 Angular 中,至少有一个模块作为 根模块 ;根模块中至少有一个组件作为 根组件 。这个根模块一般命名为 AppModule ;这个根组件一般命名为 AppComponent 。按照前面所说 Angular 的命名规则, AppModule 文件名为 app.module.ts; AppComponent 文件名为 app.component.ts。这就是 Angular CLI 为我们生成的几个文件的来历。

了解到这一点,下面我们打开 app.module.ts 文件:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

后缀名 ts 意味着 Angular 的项目使用 TypeScript 编写。Angular 提供多种语言开发:ES6,Dart,TypeScript。但官方推荐的是使用 TypeScript。几乎所有 Angular 教程都是使用 TypeScript。因此,我们也选择使用 TypeScript 进行学习。在一定程度上说,这是必须的,因为虽然 Angular 提供了多种语言的开发方式,但 Angular 本身就是用 TypeScript 开发的。

TypeScript 是 JavaScript 的超集。任何合法的 JavaScript 都是合法的 TypeScript。TypeScript 提供了比 JavaScript 更多的功能,比如完整的类型系统、修饰器等。有过 Java 或者 C# 开发经验的开发者很容易上手 TypeScript。这里我们不会详细介绍 TypeScript,而是在使用中慢慢接触解释有关 TypeScript 的相关内容。

TypeScript 有类的概念。因此,我们可以很明显地看到代码最后一行 export class AppModule { } ,是如何将一个类导出的。 export 关键字来自 ES6,意味着这个类 AppModule 可以在其它模块使用。注意,这里所说的“模块”,不是 Angular 的模块,而是 ES6 系统中的模块。ES6 模块与 Angular 模块有本质区别。ES6 模块是语言级别的,每个 文件 是一个模块,文件中定义的所有对象都从属于那个模块。 通过 export 关键字,模块可以把它的某些对象声明为公共的。 其它 JavaScript 模块可以使用 import 语句访问这些公共对象。

JavaScript,ES,ES6 和 ES2015

ES 是 ECMAScript 的缩写。ECMAScript 是一个标准,由 ECMA 国际(前身为欧洲计算机制造商协会,英文名称 European Computer Manufacturers Association)通过 ECMA-262 标准化的脚本程序设计语言。JavaScript 是 ECMAScript 的一种实现。ECMAScript 还有其它实现,比如 ActionScript。 2015年6月,ECMAScript 6.0(ES6)正式发布,也就是 JavaScript 语言的下一代标准。ECMA 国际为了更频繁地发布包含小规模增量更新的新版本,将于 2016 年发布的新标准命名为 ECMAScript 2016。之后的新版本将按照 ECMAScript + 年份的形式命名发布。因此,按照这个规定,于 2015 年发布的 ES6 被重新命名为 ES2015。因此,ES6 和 ES 2015 仅是同一标准的不同称呼而已。

Angular 自带了一组 JavaScript 模块,可以把它们看成库模块。每个 Angular 库的名称都带有 @angular 前缀。 使用 JavaScript 的  import 语句导入其中的各个部分。比如,

import { BrowserModule } from '@angular/platform-browser';

就是从 JavaScript 模块 @angular/platform-browser 导入了 Angular 模块 BrowserModule

我们希望把 TypeScript 的类作为 Angular 的模块或者组件的基础。这是很自然的想法:面向对象设计思想告诉我们,模块或者组件天然就是一个对象。那么,如果确定一个类是模块还是组件,还是其它什么东西呢?Angular 选择使用装饰器来标明。装饰器( Decorator )这个名词来自 Python,在 Java 中被称为“注解 Annotation”,在 C# 中被称为“属性 Attribute”。

为什么 AppModule 是一个 Angular 模块呢?因为它使用了 @NgModule 装饰器。被 @NgModule 装饰器装饰的类,Angular 就认为是一个模块。而这个装饰器,也是从一个 JavaScript 模块中导入的:

import { NgModule } from '@angular/core';

除了 @NgModule ,Angular 还提供了很多其它的装饰器。我们会在后面详细介绍这些装饰器。

@NgModule 装饰器接受一个 JSON 对象作为参数:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

declarations 表示这个模块中 声明 了哪些组件。前面说过,组件必须隶属于一个模块,也就是说,一个组件必须在某一个模块进行声明。并且,一个组件只能在一个模块中进行声明。上面的代码中,AppModule 声明了 AppComponent 组件。需要指出的是, declarations 中不仅仅是组件,还可能有其它元素,比如指令等。我们会在后面再介绍这部分内容。

imports 表示这个模块 导入 了哪些模块。前面说过,模块之间可以相互引用。引用的方式就是导入其它模块。这里,AppModule 导入了 BrowserModule,因此就可以使用 BrowserModule 中公开的组件或其它元素。

providers 表示这个模块 提供 了哪些服务。服务是一般作为逻辑的抽象。组件通过服务实现自己的业务逻辑。比如,有的服务提供了 HTTP 请求,有的服务提供了用户状态管理等。

bootstrap 表示这个模块 启动 哪些组件。应用程序在启动时会引导根模块 AppModule ,将其作为一个入口组件 entryComponent 。引导中会创建所有列出在 bootstrap 中的组件,然后将其插入 DOM,形成一棵组件树。虽然 bootstrap 是一个数组,但一般一个应用程序只有一棵组件树,也就是只有一个引导组件。这个组件通常被称为 AppComponent。

AppComponent 是 Angular CLI 生成的另外一个重要的部分。与 AppModule 不同的是,AppComponent 由四个文件构成,这四个文件具有类似的命名:通常以 component 作为中间名,后缀名不同。这与 app.module.ts 是一致的。组成 AppComponent 的四个文件分别是:

  • app.component.ts:AppComponent 的类所在文件
  • app.component.spec.ts:AppComponent 单元测试代码文件
  • app.component.html:AppComponent 的 HTML 渲染文件
  • app.component.css:AppComponent 的样式文件

我们从 app.component.ts 开始看起:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'todomvc';
}

AppModule 类似, AppComponent 同样只是一个普通的 TypeScript 类。区别在于,后者使用 @Component 装饰器修饰。顾名思义, @Component 用于标识一个类是一个组件。这个装饰器,同样是从 JavaScript 模块 @angular/core 导入的。 @Component 装饰器也接受一个 JSON 对象作为参数。在 AppComponent 中, @Component 使用了下面几个参数:

  • selector :字符串类型的选择器,其使用与 CSS 选择器类似。例如,这里设置 selector: 'app-root' ,那么,我们在 HTML 中使用 <app-root></app-root> 即可使用这个组件。也就是说,我们创建了一个新的 HTML 标签。同样,我们也可以使用 selector: '[appRoot]' ,注意 [appRoot] 其实就是 CSS 的属性选择器的语法,类似的,我们就需要使用 <div appRoot></div> 来使用这个组件。一般而言,我们通常会将组件作为新的 HTML 标签,但某些情况下则需要使用另外的技巧。我们会在实际应用中看到这些内容。
  • templateUrl :模板 URL。如果我们把组件看作新的 HTML 标签,浏览器在遇到这个新的标签时,需要知道要如何渲染这个标签,也就是这个组件的模板。Angular 使用 templateUrl 指定组件模板文件的位置。
  • styleUrls :样式表 URL。 templateUrl 定义了组件模板文件的位置,模板文件确定了组件的结构,组件的样式则需要使用 CSS 文件定义,也就是这里的 styleUrls 。注意, styleUrls 的类型是一个数组,因此,一个组件可以有多个样式表文件。

回到 app.component.ts,我们通过 @Component 的参数就可以知道,AppComponent 的选择器是 app-root ,其模板文件路径是 ./app.component.html,其样式表文件路径是 ./app.component.css。后两者都是通过相对路径指定了文件的位置。也就是说,app.component.html 和 app.component.css 与 app.component.ts 是同目录的。

Angular CLI 为我们生成的 AppComponent 类只有一个属性: title ,其值被设置为 todomvc。

app.component.html 的内容则是:

<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
  <h1>
    Welcome to {{ title }}!
  </h1>
  <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<h2>Here are some links to help you start: </h2>
<ul>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
  </li>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
  </li>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
  </li>
</ul>

这是一个普通的 HTML 片段,除了有一个特殊的 {{title}} 语法。这里简单说一下,这个语法意味着,这个位置的内容会被 绑定 到 AppComponent 类的 title 属性。 {{title}} 的内容会被自动替换为 title 属性的值。注意我们说的是“绑定”,这意味着,当 title 值改变时, {{title}} 的值会自动随之改变。我们会在后面详细介绍这部分内容。

app.component.css 的内容是空白的,也就是不添加任何特殊的样式。

好了,现在模块和组件都准备好了,并且组件也被添加到了模块。前面我们说过,这样定义好之后,使用 <app-root></app-root> 就可以使用 AppComponent 。这部分代码在哪里呢?现在打开 index.html,我们就会看到:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Todomvc</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>

Angular CLI 在这里通过 <app-root></app-root> 使用了 AppComponent 组件。因此,我们能够在屏幕上看到浏览器渲染出来的页面。

现在,我们大致了解 Angular CLI 生成的文件,以及 Angular 中最重要的组件和模块的含义。之后的章节中,我们将在此基础上,逐步实现 TodoMVC 应用所要求的各种功能。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

运营笔记

运营笔记

类延昊 / 天津人民版社 / 2016-12-1 / CNY 39.80

运营是入门浅但学问深的行当。一个入门很久的人不见得能在11年内爬到塔尖,同样一个初入龙门的人占据高位也不见得非用11年。 到底该怎么做运营?如何做运营才不至于让自己忙死累死甚至茫然不知所措?如何和用户进行有效沟通?如何把握住处于塔尖20%的核心用户?如何强敌逼阵时快速找到突破口?如何挤破头皮提高转化率? 在这本书里,类类以自己常年战斗在一线摸爬滚打的经验给予了有效而真诚的解答。一起来看看 《运营笔记》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具