创建Angular项目

1. 说明

本项目使用的 angular, nodejs, npm, cnpm 版本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ng version
Angular CLI: 16.2.10
Node: 18.13.0
Package Manager: npm 8.19.3
OS: linux x64

Angular:
...

Package Version
------------------------------------------------------
@angular-devkit/architect 0.1602.10 (cli-only)
@angular-devkit/core 16.2.10 (cli-only)
@angular-devkit/schematics 16.2.10 (cli-only)
@schematics/angular 16.2.10 (cli-only)

2. 打开命令行工具找到你要创建项目的目录

3. 创建项目

3.1. 创建项目命令

1
ng new <工作空间名称>

3.2. 创建项目示例

1
2
ng new <workspace_name>
# e.g. ng new angulardemo

如果要跳过依赖安装, 可以添加--skip-install

1
2
ng new --skip-install <workspace_name>
# e.g. ng new --skip-install angular-demo

3.3. 输入参数

执行以上命令是, 系统会询问两个问题

  1. 是否添加路由.
    如果创建项目的目的为了体验 angular 的指令, 模板, 语法, 编译过程等等, 不涉及页面跳转, 可以不需要添加路由.
    如果需要涉及到页面之间的跳转, 则需要添加路由功能.

     > 如果创建项目过程中下载依赖包不成功, 可以停止, 然后手动输入`cnpm install`安装依赖包
     > 使用--skip-install选项. 由于npm install经常会出现卡住没有反应的现象, 在创建项目过程中可以跳过安装依赖, 等项目结构创建完成后手动安装依赖包
     > 此时可以添加选项 --skip-install 例如 `ng new angulardemo --skip-install`
    
  2. stylesheet 样式格式
    现代 web 开发, 已经不止 css 一种样式语法, stylesheet 技术也在不断的进步和升级. angular 集成的 stylesheet 包括传统的 css 样式, less, sass, scss, stylus. 这里可以选择自己擅长的技术. 选择样式意为着 angular cli 会帮我们添加相应依赖, 解析器, 配置. 在实际开发过程中, 我们也可以混合使用以上技术. 这些样式最终会被解析器, 编译成浏览器可以识别的 css 代码.

     > 如果要在命令行中指定css预处理器, 可以选项`--style` 例如 `ng new angulardemo --style=scss` 来指定
    

3.4. 项目目录结构介绍

执行完以上命令后系统会为我们创建很多文件. 下面对这些文件进行简单介绍.
执行完以上命令后, 使用 tree 命令查看项目的目录结构树大致如下.

1
tree
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
├-angular-demo
├── angular.json
├── package.json
├── README.md
├── src
│   ├── app
│   │   ├── app.component.html
│   │   ├── app.component.scss
│   │   ├── app.component.spec.ts
│   │   ├── app.component.ts
│   │   ├── app.module.ts
│   │   └── app-routing.module.ts
│   ├── assets
│   ├── favicon.ico
│   ├── index.html
│   ├── main.ts
│   └── styles.scss
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json

3.4.1. 一级目录介绍

目录说明
node_modulesnpm install安装依赖包时,第三方依赖包存放在 node_modules 下
src应用源代码目录
.angular.jsonAngular 命令行工具的配置文件。后期可能会去修改它, 引一些其他的第三方的包 比如 jquery 等
package.json这是一个标准的 npm 工具的配置文件,这个文件里面列出了该应用程序所使用的第三方依赖包。实际上我们在新建项目的时候,等了半天就是在下载第三方依赖包。下载完成后会放在 node_modules 这个目录中,后期我们可能会修改这个文件。
package-lock.jsonpackage-lock.json 是在 npm install时候生成一份文件,用以记录当前状态下实际安装的各个 npm package 的具体来源和版本号.
README.md项目说明文件
tsconfig.json是 typescript 的配置文件,用于配置 typescript 编译的一些选项.
tsconfig.app.jsontsconfig.app.json 是 tsconfig.json 的扩展. TypeScript 编译器的配置,添加第三方依赖的时候会修改这个文件, 用于指定编译,打包,运行时的一些 ts 选项.
tsconfig.spec.jsontsconfig.spec.json 也是 tsconfig.json 的扩展, 用于指定运行测试时的一些 ts 选项.

3.4.2. 二级目录介绍

src 目录:

目录说明
app 目录包含应用的组件和模块,我们要写的代码都在这个目录
assets 目录资源目录,存储静态资源的 比如图片
favicon.icofavicon.ico 是一个图标文件,也被称为“网站图标”、“页面图标”。
index.html整个应用的根 html,程序启动就是访问这个页面
main.ts整个项目的入口点,Angular 通过这个文件来启动项目
styles.css主要是放一些全局的样式

3.4.3. 三级目录介绍

src/app 目录

app 目录是我们要编写的代码目录。我们写的代码都是放在这个目录。

一个 Angular 程序至少需要一个模块和一个组件。在我们新建项目的时候命令行已经默认生成出来了。

在 src/app 下可以建立更多子目录, 来存放相应的元素, 比如 component 存放到 src/app/components 下,

service 存放到 src/app/services 下, pipe 存放到 src/app/pipes 目录下.

3.4.4. 项目是如何启动的

上一节我们讲到了 angular 项目的目录结构, 在如此复杂的目录结构中, 我们第一想了解, 也是应该了解的是项目的入口文件是哪个?

如果是做 c, c++, java 约定俗成的是找 main 方法. 在 web1.0, 2.0 开发中是找 index.html.

以下是项目生成后的 index.html, 从该文件中我们能一眼看出项目的入口文件在哪里吗?
有人说, 我一眼能看出是<app-root></app-root>, 如果你认为项目的入口是 app-root 这个 component 的话, 那就是踏入了一个陷阱, 或者被误导了, 或者是一种想当然. 无论是 angularjs 的class='app'也好, 还是 vue 的<app />也好, react 的<div id="root"></div>, 这些主 component 或者根 component 的渲染都不是项目入口位置.

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>AngularDemo</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>

如果对以上观点有疑问,可以打开 app-root 这个 component 看看.
从根 component 我们能看出, 服务是从哪里加载的吗, 路由是哪里加载的吗, 项目依赖的模块有哪些吗? 答案是不能, 而根 component 也只是众多普通 component 中的一个.

1
2
3
4
5
6
7
8
9
10
import { Component } from "@angular/core";

@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"],
})
export class AppComponent {
title = "angular-demo";
}

而项目真正的入口实际上是 src/main.ts, 所以在 angular 开发中. 我们依然要找 main, 而这个 main 不是 main 方法或函数, 而是一个 main.ts 文件.

1
2
3
4
5
6
7
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";

import { AppModule } from "./app/app.module";

platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));

这里的 main.ts, 也是一个默认的入口文件, 他是在 angular.json 的配置文件中指定的. 也就是说, 入口文件也是可以被修改的, 但是为了项目更好的可维护性,如非必要建议不要去修改入口文件的名字.
本来入口文件就很难找到了, 还要将其修改为一个更难理解的名字, 对 new joiner 是很不友好的, 毕竟项目需要更多的 new joiner 来维护, 改成一个更不约定俗成的名字, 对于新手无异于是当头棒喝. 对于一个 angular 老手来说, 当我们打开一个 angular 项目后, 还是要看看 angular.json 的指定的主文件到底是不是 src/main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

"options": {
"outputPath": "dist/angular-demo",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
},

知道了 main.ts 是入口文件后, 我们很容易就会发现, 项目启动使用的是下面这一行代码.
很容易猜测到 AppModule 里面应该会包含更多的信息, 怎么做到的? 靠得是一个开发者的嗅觉? :), 这是事后诸葛亮的的说法.
当然是靠探索精神, 当你拿到这样一段代码后, 当然要开始探索, 首先 ctrl+click 进 platformBrowserDynamic 发现是 angular 的 api, 不是一下下就能懂的.
然后在 ctrl+click 进 AppModule, 一下就看到了 component, services. 当然回过头来我们也要刨析一下 platformBrowserDynamic 和 bootstrapModule, 但是这里我们先刨析 app.module.ts 这个文件.

1
2
3
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));

声明的第一部分 platformBrowserDynamic()创建了一个平台。Angular 文档将该平台描述为:

网页上 Angular 的入口点。每个页面都只有一个平台,并且该页面上运行的每个 Angular 应用程序所共有的服务(例如反射)都绑定在其范围内。

Angular 还有一个running application instance的概念,您通常可以使用令牌注入该实例 ApplicationRef。一个平台上可能有许多应用程序。每个应用程序都是从基于 Module 定义使用 bootstrapModule 创建的。正如示例中 main.ts 所做的一样, 首先创建一个平台,然后创建应用程序实例。

创建应用程序时,Angular 会检查模块( 例如: AppModule)的 bootstrap 属性用于引导应用程序的:

1
2
3
4
5
6
7
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, AppRoutingModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}

bootstrap 属性通常引用您想要用来引导应用程序的组件。然后 Angular 在 DOM 中找到引导组件的选择器元素并初始化该组件。

打开 app.module.ts, 可以看到, 项目的 bootstrap(引导程序)是 AppComponent.
从这里我们可以看出, 项目需要首先加载 AppComponent, BrowserModule, 然后启动 AppComponent, 由于 main.ts 会被编译挂载到 index.html 的<script></script>区域.
所以 angular 会在 index.html 中根据 AppComponent 的选择器selector: 'app-root' 找到<app-root></app-root>所处的位置渲染根 component. 至此我们基本了解 angular 的启动过程了.

bootstrap 的数据类型是 array, 所以很明显, bootstrap 属性可以指定多个 component, 回到 index.html, 说明 angular 是支持多根组件的, 也即 index.html 中可以指定多个根组件<app-root></app-root>

打开编译后的 index.html 文件, 我们可以看到更加清晰的 angular SPA 程序的启动加载过程.
首先向服务器请求 index.html, 然后加载 runtime.js, polyfills.js, 异步加载 styles.js, vendor.js, main.js,
最后渲染 app-root 组件. 如果路径是子目录, 例如http://localhost:4200/login 则涉及到 angular 路由的知识, 将在我的另一篇文章 angular 路由中讲到, 关注鹏叔的博客空间,查找更多 angular 相关文章.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>AngularDemo</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<app-root></app-root>
<script src="runtime.js" type="module"></script>
<script src="polyfills.js" type="module"></script>
<script src="styles.js" defer></script>
<script src="vendor.js" type="module"></script>
<script src="main.js" type="module"></script>
</body>
</html>

3.4.5. 重点文件介绍

3.4.5.1. angular.json 文件详解

angular.json 也叫 Angular 工作空间配置,在 Angular 6 以前该配置的文件名为 angular-cli.json 是 angular cli 的配置文件,Angular 6 以后进行了重命名,但是主要职责还是作为 Angular cli 的配置文件。

在了解 angular.json 配置文件之前我们需要首先了解 Angular 中的三个概念:

  • 工作空间(Workspace)
  • 应用(Application)
  • 类库(Library)

当我们使用ng new [name]实际创建的是一个工作空间(Workspace), angular.json 文件位于工作空间(Workspace)根目录。

一个工作空间(Workspace), 可以包含多个 Application 和 library, application 可以使用ng generate application命令创建, library 可以使用ng generate library命令创建。

当我们使用ng new [name]创建工作空间(Workspace)时,该命令也会创建一个默认的 application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json", // JSON Schema 是一个允许我们注解和验证JSON数据格式的工具。Angular CLI使用它来强化对于Angular Workspace schema的解释说明。
"version": 1, // 配置文件的版本
"newProjectRoot": "projects", // 这个属性定义了由CLI创建的新的内部应用和库放置的位置。默认值为`projects`
"projects": {
//包含工作区中每个库或应用程序的配置信息。
"angular-demo": {
// 项目名称
"projectType": "application", //项目类型
"schematics": {
// 作为Angular DevKit的一部分,用来转换、创建 或者 更新项目开发的工作流工具。
"@schematics/angular:component": {
"style": "scss" // 创建component时,使用scss样式格式
}
},
"root": "", // 该项目文件的根目录,相对于工作空间目录。初始应用程序为空,它位于工作区的根目录。
"sourceRoot": "src", // 该项目源文件的根目录。
"prefix": "app", // Angular 在创建的选择器前面添加的字符串。可以进行定制以识别应用程序或功能区域。
"architect": {
// 任何项目都可以自定义 自动化命令,如 打包、serve、test、lint等等。这些都是基于prebuilt builders ,叫做Architect Targets。
// 配置ng build命令选项的默认值。有关详细信息,请参阅[构建目标部分](https://angular.io/guide/workspace-config#build-target)
"build": {
// 用于创建此目标的构建工具的 npm 包。应用程序的默认构建器 ( ng build myApp) 是@angular-devkit/build-angular:application,
// 它使用esbuild包捆绑器。
// 每个目标对象都指定了该目标的 builder,它是 architect 所运行工具的 npm 包
"builder": "@angular-devkit/build-angular:browser",
// 此部分包含默认构建目标选项,但是会被命令行选项覆盖。请参阅[默认构建目标部分](https://angular.io/guide/workspace-config#default-build-targets)。
"options": {
"outputPath": "dist/angular-demo",
"index": "src/index.html",
"main": "src/main.ts",
// js 垫片
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
// 包含一些用于添加到项目的全局上下文中的静态文件路径
// 每个 build 目标配置都可以包含一个 assets 数组,它列出了当你构建项目时要复制的文件或文件夹。
// 默认情况下,会复制 src/assets/ 文件夹和 src/favicon.ico
"assets": ["src/favicon.ico", "src/assets"],
// 包含一些要添加到项目全局上下文中的样式文件(即全局样式)
"styles": ["src/styles.scss"],
// 包含一些 JavaScript 脚本文件,用于添加到项目的全局上下文中。
// 这些脚本的加载方式和在 index.html 的 <script> 标签中添加是完全一样的。
"scripts": []
},

// 此部分定义不同目标环境的备用构建配置。它包含针对每个目标环境的配置,该部分为该预期环境设置默认选项
"configurations": {
"production": {
// 全部或部分应用的默认尺寸预算的类型和阈值。
// 当构建的输出达到或超过阈值大小时,你可以将构建器配置为报告警告或错误
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
// 默认情况下,该ng build命令使用production配置,该配置应用了多项构建优化
// 包括:捆绑文件,尽量减少多余的空白,删除注释和死代码,重写代码以使用简短的、损坏的名称,也称为缩小
"defaultConfiguration": "production"
},
"serve": {
// 覆盖构建默认值并为ng serve命令提供额外的服务默认值。除了ng build命令可用的选项之外,它还添加了与serve应用程序相关的选项。
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "angular-demo:build:production"
},
"development": {
"browserTarget": "angular-demo:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
// 为 ng xi18n 命令所用到的 ng-xi18n 工具选项配置了默认值
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "angular-demo:build"
}
},
"test": {
// 覆盖测试时的构建选项默认值,并为 ng test 命令提供额外的默认值以供运行测试
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": ["zone.js", "zone.js/testing"],
"tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "scss",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.scss"],
"scripts": []
}
}
}
}
}
}

3.4.6. 刨析一个 component

创建 component 可以使用

1
ng g c component_path/component_name

这里的 g 表示 generate 生成的以上, c 表示 component, 最好使用 component_path 给 component 指定一个保存路径, 不至于使得项目过于扁平, 而使得 component 文件散落在项目根目录下. 命令执行完成后, 在 component_path/component_name 目录下会指定创建 html, style, 测试文件, typescript 等组件相关的文件.

3.5. 启动项目

3.5.1. 启动项目可以使用如下命令

1
ng serve --open

–open 指定该选项会在服务器启动后自动打开项目首页,
也可以手动在浏览器端输入网站访问项目首页http://localhost:4200/

4. 创建新组件(component)

4.1. 使用命令行创建新组建

1
2
3
4
ng g component path/component_name
# 例如
ng g component components/news

另外使用 ng g 可以创建以下 angular 元素:

5. angular 数据绑定

这里我们创建一个 component, 并将其命名为 TestDataBindingComponent, 用于测试数据绑定.

1
ng new component components/TestDataBinding

命令说明:

  • ng 是 angular cli 的主命令
  • new 为新建 angular 元素的子命令
  • component 为 angular 元素的类型, 更多元素可以参考上一节的 angular 元素列表
  • components/TestDataBinding 其中 components 为元素的存放路径, TestDataBinding 为元素名称, 元素名称不必添加 component 后缀, angular 会自动在创建元素时添加 component 后缀作为完整的元素名称.
  • 执行以上命令后, angular 会在 components 目录下创建一个名为 test-data-bingding 的子目录, 里面会存储与 conponent 相关的 typescript, 样式文件, html 文件, 以及测试文件. 同时该命令会修改 src/app/app.module.ts, 自动添加对该 component 的引用.
  • 如果执行以上命令后, 发现拼写, 或者路径有误, 需要反悔时, 只需要删除 components/test-data-bingding 整个目录, 并修改 src/app/app.module.ts 将相关引用删除, 即可彻底清除该 component. 当然在熟悉 angular 的原理以后, 发现问题可以做局部的修改, 这里不做展开.

6. 相关阅读

最新更新以及更多 Angular 相关文章请访问 Angular 合集 | 鹏叔的技术博客

7. 参考文档

Angular 工作空间配置(angular.json)

Angular workspace configuration

angular.json 简单解释