趁着学习Angular官方教程的同时,也学习热加载和MVVM等知识
首先
在前一篇文章中,我建立了一个基于Docker的Angular环境。
我将应用程序命名为sample-angular-on-docker。
这次我们将进行Angular官方教程中的《教程:英雄之旅》。
本教程将按照以下章节进行。
-
- イントロダクション
-
- プロジェクトの作成
-
- 1.ヒーローエディター
-
- 2.リストの表示
-
- 3.フィーチャーコンポーネントの作成
-
- 4.サービスの追加
-
- 5.ナビゲーションの追加
- 6.サーバーからデータの取得
基本上,我会按照教程进行操作,不会写出重复的文章。
我会将每章卡壳的地方和需要牢记的要点留作文章。
各种积分
按照本文的标题所述,在做教程的同时,我们还可以学习到很多其他的知识。以下是主要的要点。
-
- [POINT] ホットリロード
-
- [POINT] ディレクトリ構成
-
- [POINT] 「spec」って何?
-
- [POINT] component と service の違い
- [POINT] その他
[POINT] 热重载
当文件更新时,如果能够进行热重载,我会感到非常高兴。经过调查,发现只需要在启动选项中设置 –poll 参数即可。
因此,在启动时,请使用以下设置。
# こっちじゃなくて
root@60ff460a2f75:/projects/app# ng serve --host 0.0.0.0
# こっちを使う事で、ホットリロードができる
root@60ff460a2f75:/projects/app# ng serve --host 0.0.0.0 --poll 1 # 起動オプション --poll を指定
[POINT] 目录结构
项目创建后的目录结构
刚创建项目的目录结构如下。
.
├── README.md
├── angular.json
├── karma.conf.js
├── package-lock.json
├── package.json
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.spec.json
├── .browserslistrc
├── .editorconfig
├── .gitignore
├── .vscode
| └── (省略)
├── node_modules
| └── (省略)
└── src
├── app
│ ├── app-routing.module.ts
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ └── app.module.ts
├── assets
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── main.ts
├── polyfills.ts
├── styles.css
└── test.ts
教程完成后的目录结构
当你继续进行教程时会发现,每次使用Angular CLI执行组件、服务等操作时,app/目录下会生成零散的文件。
.
├── README.md
├── angular.json
├── karma.conf.js
├── package-lock.json
├── package.json
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.spec.json
├── .browserslistrc
├── .editorconfig
├── .gitignore
├── .vscode
│ └── (省略)
├── node_modules
│ └── (省略)
└── src
├── app <—————————- app下面真是太多了!这样管理不了啊 X-(
│ ├── dashboard
│ │ ├── dashboard.component.css
│ │ ├── dashboard.component.html
│ │ ├── dashboard.component.spec.ts
│ │ └── dashboard.component.ts
│ ├── hero-detail
│ │ ├── hero-detail.component.css
│ │ ├── hero-detail.component.html
│ │ ├── hero-detail.component.spec.ts
│ │ └── hero-detail.component.ts
│ ├── hero-search
│ │ ├── hero-search.component.css
│ │ ├── hero-search.component.html
│ │ ├── hero-search.component.spec.ts
│ │ └── hero-search.component.ts
│ ├── heroes
│ │ ├── heroes.component.css
│ │ ├── heroes.component.html
│ │ ├── heroes.component.spec.ts
│ │ └── heroes.component.ts
│ ├── messages
│ │ ├── messages.component.css
│ │ ├── messages.component.html
│ │ ├── messages.component.spec.ts
│ │ └── messages.component.ts
│ ├── app-routing.module.ts
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.component.spec.ts
│ ├── app.component.ts
│ ├── app.module.ts
│ ├── hero.service.spec.ts
│ ├── hero.service.ts
│ ├── hero.ts
│ ├── in-memory-data.service.spec.ts
│ ├── in-memory-data.service.ts
│ ├── message.service.spec.ts
│ ├── message.service.ts
│ └── mock-heroes.ts
├── assets
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── main.ts
├── polyfills.ts
├── styles.css
└── test.ts
目录结构(MVVM/最终形式)
在进行源代码管理时,目录结构非常重要,但是并没有明确的最佳实践。
如果你搜索一下,会发现以下类似的文章。
-
- https://blog.lacolaco.net/2019/07/angular-ngmodule-and-directories/
-
- https://mya-ake.com/slides/regret-angular-web-app
- https://mattarishitemota.com/?p=510
在教程中虽然提到了按”域名单位”或”类型单位”进行区分,但在教程阶段并不存在这样的内容。
(嗯,虽然存在,但我不想考虑)
基於MVVM架構,我們可以將Angular直接組織成目錄結構,如此一來就完成了。所以我們按照MVVM的方式組織了目錄。
.
├── README.md
├── angular.json
├── karma.conf.js
├── package-lock.json
├── package.json
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.spec.json
├── .browserslistrc
├── .editorconfig
├── .gitignore
├── .vscode
| └── (省略)
├── node_modules
| └── (省略)
└── src
├── app <—————————- 变得更加清晰明了了 🙂
│ ├── app-routing.module.ts
│ ├── app.module.ts
│ ├── view
│ │ ├── app.component.css
│ │ ├── app.component.html
│ │ ├── app.component.spec.ts
│ │ ├── app.component.ts
│ │ ├── dashboard
│ │ │ ├── dashboard.component.css
│ │ │ ├── dashboard.component.html
│ │ │ ├── dashboard.component.spec.ts
│ │ │ └── dashboard.component.ts
│ │ ├── hero-detail
│ │ │ ├── hero-detail.component.css
│ │ │ ├── hero-detail.component.html
│ │ │ ├── hero-detail.component.spec.ts
│ │ │ └── hero-detail.component.ts
│ │ ├── hero-search
│ │ │ ├── hero-search.component.css
│ │ │ ├── hero-search.component.html
│ │ │ ├── hero-search.component.spec.ts
│ │ │ └── hero-search.component.ts
│ │ ├── heroes
│ │ │ ├── heroes.component.css
│ │ │ ├── heroes.component.html
│ │ │ ├── heroes.component.spec.ts
│ │ │ └── heroes.component.ts
│ │ └── messages
│ │ ├── messages.component.css
│ │ ├── messages.component.html
│ │ ├── messages.component.spec.ts
│ │ └── messages.component.ts
│ ├── viewmodel
│ │ ├── hero.service.spec.ts
│ │ ├── hero.service.ts
│ │ ├── in-memory-data.service.spec.ts
│ │ ├── in-memory-data.service.ts
│ │ ├── message.service.spec.ts
│ │ └── message.service.ts
│ └── model
│ ├── hero.ts
│ └── mock-heroes.ts
├── assets
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── index.html
├── main.ts
├── polyfills.ts
├── styles.css
└── test.ts
順带一提,使用Angular CLI创建组件和服务会在app/文件夹下创建,但执行命令时也可以创建文件夹。
因此,在使用Angular CLI进行代码维护时,我认为最好是在确定文件夹结构的基础上,对执行命令进行限制来进行操作。
# これだと app/ 配下に作られるので、管理しづらい
root@c773d67c1823:/projects/app# ng generate component heroes
# これだと app/view/ 配下に作られるので、管理しやすくなる
root@c773d67c1823:/projects/app# ng generate component view/heroes
「spec」是什么意思?
使用Angular CLI生成组件和服务时,会生成一个名为xxxx.component.spec.ts的文件。
# component の生成
root@c773d67c1823:/projects/app# ng generate component heroes
Node.js version v19.0.0 detected.
Odd numbered Node.js versions will not enter LTS status and should not be used for production. For more information, please see https://nodejs.org/en/about/releases/.
CREATE src/app/heroes/heroes.component.css (0 bytes)
CREATE src/app/heroes/heroes.component.html (21 bytes)
CREATE src/app/heroes/heroes.component.spec.ts (599 bytes) <---------- なにこれ!!!!!!!!!!!!!!
CREATE src/app/heroes/heroes.component.ts (275 bytes)
UPDATE src/app/app.module.ts (475 bytes)
# service の生成
root@c773d67c1823:/projects/app# ng generate service hero
Node.js version v19.0.0 detected.
Odd numbered Node.js versions will not enter LTS status and should not be used for production. For more information, please see https://nodejs.org/en/about/releases/.
CREATE src/app/hero.service.spec.ts (347 bytes) <---------- なにこれ!!!!!!!!!!!!!!
CREATE src/app/hero.service.ts (133 bytes)
这个 xxxx.component.spec.ts 在教程中不会被使用。
不使用它,所以不明白它生成的目的是什么。
经过调查,似乎是针对单独测试执行的文件。
以下是官方网站。
- https://angular.jp/guide/testing-components-basics
组件和服务的区别
先前一直混用了组件和服务这两个词,但事实上,我并不真正了解它们的意思。
当我进行调查时,在官方网站上发现了以下内容。
请看官方网站下文。
- https://angular.jp/guide/architecture
组件定义了视图。
视图是从程序逻辑和数据中由Angular选择和更改的可变屏幕元素的集合。每个应用程序至少有一个根组件。
组件使用服务来提供与视图无直接关系的特定功能。
服务提供者可以作为依赖项被注入到组件中,以模块化和有效地实现代码的重用。
我明白了。在这里,MVVM的观点开始生效。
将服务注入到组件中,这意味着这是数据绑定的机制。
因此,组件是视图,服务相当于视图模型。
了解了View和ViewModel,那Model呢?
‘似乎 ng generate interface {name} 命令可以生成与 Model 相当的内容。在教程中,hero.ts 可能相当于它,但是由于不是通过命令而是直接创建文件,从 MVVM 的角度来看可能不太明显。’
如果尝试执行上述命令,会生成以下文件(与hero.ts具有相同的结构,所以我认为这就是一个模型)。
# interface の生成
root@c773d67c1823:/projects/app# ng generate interface model/dummy
Node.js version v19.0.0 detected.
Odd numbered Node.js versions will not enter LTS status and should not be used for production. For more information, please see https://nodejs.org/en/about/releases/.
CREATE src/app/model/dummy.ts (27 bytes)
# ファイルの確認
root@c773d67c1823:/projects/app# cat src/app/model/dummy.ts
export interface Dummy {
}
[POINT] 其他
在推进教程的过程中,除了仅能进行表面上的理解之外,还有一些用法不太能理解的。嗯,随着开发的进行,我会逐渐适应的,所以现在只需要把它们当作“原来有这样的东西”就好了。
-
- データバインディングには ngModel を用いる
ngModel を使用するには、 FormsModule のimportが必要
https://angular.jp/api/forms/NgModel
classバインディングは、以下を参照
これは特に import が必要などは書かれていない
https://angular.jp/guide/class-binding
*ngFor と *ngIf で html を操作
ルーティングは ./app/app-routing.module.ts で行われて、 を使う
完成教程
我明白了如何构建,但关键的概念和规约在教程中并没有被掌握。所以,我将参考官方网站的以下内容,继续学习。
-
- Angularの概念の紹介
https://angular.jp/guide/architecture
Angularコーディングスタイルガイド
https://angular.jp/guide/styleguide
用語集
https://angular.jp/guide/glossary