https://github.com/jackchoumine/stock-market
angular学习记录
https://github.com/jackchoumine/stock-market
Last synced: 2 months ago
JSON representation
angular学习记录
- Host: GitHub
- URL: https://github.com/jackchoumine/stock-market
- Owner: jackchoumine
- Created: 2020-11-02T16:01:59.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2020-12-27T18:50:51.000Z (over 4 years ago)
- Last Synced: 2025-01-17T13:30:31.297Z (4 months ago)
- Language: TypeScript
- Size: 354 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# StockMarket
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.3.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
# 学习笔记
《angular 即学即用》是一本 ng 的入门指南,全书代码基于`angularJS 5.0.0`,全书专注所有 ng 开发人员都必须知道的内容,而不关注只对一部分人有用的内容。
代码仓库:[angular-up-and-running](https://github.com/shyamseshadri/angular-up-and-running)
学习的环境:
```bash
Angular CLI: 10.1.3
Node: 12.18.4
OS: win32 x64
npm: 6.14.6
angular core: 10.1.3
typescript: 4.0.3
```## angular VS angular.js
> [Angular](https://angular.io/) (通常是指 "Angular 2+"或"Angular v2 及更高版本 ")[4][5] 是一个基于 TypeScript 的 开源 Web 应用框架 由 Google 的 Angular 团队以及社区共同领导。Angular 是由 AngularJS 的同一个开发团队完全使用`typescript`重写的。
> [AngularJS](https://angularjs.org/) 在 2009 年由 [Miško Hevery](https://github.com/mhevery) 和 [Adam Abrons](https://github.com/abrons) 开发,作为线上 JSON 储存服务的软体,它是以兆位元来计价,便于成为企业的应用服务。当初以 "GetAngular.com" 注册网域,但由于只有少量的注册用户,在两人决定放弃这个商业想法前,就把 Angular 开源了。Abrons 后来离开了这个计划,但在 Google 工作的 Hevery 和一些谷歌员工如 Igor Minár 和 Vojta Jína 等则继续开发维护此函式库。
> 因为版本问题,没有发布 angular 3 ,直接从 angular 2 到 angular 4。
> angular.js 从 2.0 开始,不再叫 angular.js ,也不叫 angular 2、angular 4,就叫 angular。angular 团队计划每 6 个月发布一个大版本。学习 angular,可不学习 angular.js。
在 angular 的第一个版本中的一些概念比如**数据绑定**、**关注分离**、**依赖注入**的,已经成为 web 框架的通用特性。
## hello angular
安装 `typescript`、`@angular/cli`:
```bash
npm i -g typescript @angular/cli
```使用 ng 提供的命令行工具,可创建一个新项目
```bash
ng new
```> 创建项目时,安装依赖会非常慢,使用 `ng new --skip-install` 跳过依赖安装,然后使用 `yarn` 安装依赖。
ng-cli(ng 提供的命令行工具,官方不叫这个名字,我自己的说法)的使用:
三种框架都提供了生成项目的工具,这些工具为项目的初始化做了大量工作,使开发人员专注于业务的具体实现。
ng-cli 能完成以下任务:
- 引导应用程序;
- 提供服务;
- 运行测试;
- 构建;
- 新建组件、服务、路由等。```bash
ng help
ng -h # 帮助信息
ng version # 查看版本
ng serve # 运行服务,会将 TS 转译成 JS,否则浏览器识别不了
```项目的目录结构和 vue 等差不多,都有编辑器配置、依赖说明、tslint 规则等文件,主要关注 ng 特有的目录,`src` 目录内容如下:
```bash
src
│ index.html # 根 html ,类似 vue 的 html 模板
│ main.ts # 应用入口
│ polyfills.ts # 叠片代码
│ styles.scss # 全局样式代码,可引入到其他样式文件中
│ test.ts # 测试代码
│
├─app
│ │ app-routing.module.ts # 路由模块,创建是不选择路由,就没有
│ │ app.component.html # 根组件的 html 代码
│ │ app.component.scss # 根组件的样式文件
│ │ app.component.spec.ts # 根组件测试代码
│ │ app.component.ts # 根组件
│ │ app.module.ts # 主模块
│
└─environments # 环境配置目录
environment.prod.ts
environment.ts
```在项目根目录中有一个 `angular.json`,这是项目配置,新建项目时选项不同,内容也不同,类似`vue.config.js`,供项目开发和构建时使用。
[angular 规则区配置](https://angular.cn/guide/workspace-config)
### 各个文件的内容
**根 html **
```html
StockMarket
```
`app-root` 这是一个自定义标签,是在根组件内指定的,根组件对应的标签叫根元素,它是创建组件实例的标记。
> 在哪加载项目代码呢?
运行 `ng serve` 时,依赖库、程序代码、样式文件等应用资源会被打包成一个文件,动态插入到根 html 中,在浏览中访问 html,就和普通的页面一样。
**main.ts** --- 项目入口
```ts
import { enableProdMode } from "@angular/core"; // 是 es6 语法导入依赖
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";import { AppModule } from "./app/app.module";
import { environment } from "./environments/environment";// 环境检测
if (environment.production) {
enableProdMode();
}
// 引导主模块
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));
````main.ts` 是应用的入口,识别项目启动时加载的模块,还可修改**项目级别**的配置,比如 enableProMode(),关闭框架断言和验证,类似 vue 中的 `main.js`。
`app.modules.ts` 主模块,**一个应用有且只有一个主模块**。
```ts
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { StockItemComponent } from "./stock/stock-item/stock-item.component";// TS 注解,结合元数据把一个类定义为一个 ng 模块
@NgModule({
declarations: [
// 声明用到的组件和指令
AppComponent,
StockItemComponent,
],
imports: [
// 用到的其他模块
BrowserModule,
AppRoutingModule,
],
providers: [],
bootstrap: [AppComponent], // 启动项目时的入口组件
})
export class AppModule {}
```主模块是应用程序执行代码开始的地方,是应用的核心配置,加载依赖、声明应用用到的组件、标记根组件等,都在这里配置。
> declarations 定义了该模块中允许在 html 里使用的组件。任何组件在使用前都必须在**模块中**声明,一个组件只能属于一个模块。
> imports 导入用到的其他模块,从而使用这些模块中功能:组件、指令等。
> bootstrap 指定应用的**根组件**,如果没有根组件,应用不会启动,因为 ng 不知道在 index.html 中查找什么元素。
> **新增了组件、服务或者模块,通常需要修改根组件。**
**app.component.ts** 根组件
```ts
import { Component } from "@angular/core";// 装饰器,指定如何转为 HTML 代码
@Component({
selector: "app-root", // 组件标签,使用组件时的标签名字
templateUrl: "./app.component.html", // 组件模板
styleUrls: ["./app.component.scss"], // 组件样式,使用 scss 文件
})
export class AppComponent {
// 组件类,包含成员和函数
title = "stock-market";
author = "jackChouMine";
}
````selector`,CSS 选择器,从类到属性都可以,**通常使用标签选择器**;
`templateUrl`,指定组件的 html 代码,类似 vue 中的 template,可使用行内模板。```ts
`,
@Component({
template: `
})
```模板内容:
```html
hello {{title}}
my name is {{author}}
````{{}}` 是插入语法,用来绑定组件中的数据,内部是一个 JS 表达式,可修改。
`` 是我们定义的子组件,稍后会讲创建的方法。
`styleUrls`,指定组件样式,不用担心组件之间的样式相互影响。
> 指定多个样式文件,属性冲突时,优先级是怎样的?
会按照 CSS 样式的层叠特性应用到元素上。
组件类---定义组件的数据和事件处理函数。
```ts
export class AppComponent {
// 组件类,包含成员和函数
title = "stock-market";
author = "jackChouMine";
}
```组件类有双重职责:
- 呈现数据 -- view ;
- 处理组件的事件 -- control。### 总结
ng 项目的文件组织方式和相关配置。ng 组件是一个具有一些属性和装饰器的类,类封装数据和函数,装饰器指定如何处理 HTML 代码。
## 创建组件
用 `ng g component file/component-name` 可创建一个组件,file 指定组件所在的文件夹,不指定文件夹,会在 app 文件夹里创建,component-name 是组件名字。
`ng g` 是 `ng generate` 的缩写,可创建组件、`angular元素`:接口、服务、模块等。
执行该命令,会生成组件定义文件(ts 文件)、模板文件、样式文件和单元测试文件,同时还会**自动导入**到主模块中,应用就能识别它了。
导入主模块,然后在 declarations 中声明。
> 以上过程都可手动完成。
创建组件时,遵循一些惯例:
- 文件名以组件名开头,后面是元素类型,最后是扩展名。
比如 `stock-item.component.ts`,这样方便我们对文件进行分组和识别。
我们定义好的组件:
```ts
import { Component, OnInit } from "@angular/core";
import { Stock } from "../../model/stock";
@Component({
selector: "app-stock-item",
templateUrl: "./stock-item.component.html",
styleUrls: ["./stock-item.component.scss"],
})
export class StockItemComponent implements OnInit {
// NOTE 把数据封装到一个模型类里,方便集中管理
// 事件处理函数还是定义在组件中
public stock: Stock;
constructor() {
console.log("hello constructor");
}ngOnInit(): void {
console.log("OnInit");
this.stock = new Stock("Test Stock Company", "TSC", 86, 90);
}
// tslint:disable-next-line: typedef
toggleFavorite(event, param) {
console.log("用户点击了", event);
console.log("函数参数", param);
this.stock.isFavorite = !this.stock.isFavorite;
}
}
````selector: 'app-stock-item'` 组件使用的选择器(自定义标签),注意`app-`,这是组件前缀,ng 自动添加的,除非里另外指定名字。
> 如何指定?
`angular.json` 文件里,修改` "prefix": "app",`。
```ts
export class StockItemComponent implements OnInit {} // `StockItemComponent` 类实现 `OnInit` 接口。
```组件有一些生命周期函数,在特定时期执行某些操作,比如初始化、视图被呈现、销毁等。
在组件创建和 data 字段都被初始化之后,`OnInit` 函数执行,一般在此函数中做初始化工作,这样容易测试其余功能,而不是每次都触发初始化。
`ngOnInit` -- 当你想进入组件的初始化阶段,需要实现 `OnInit` 接口,然后在组件中实现 `ngOnInit` 函数,就可以在该函数中执行初始化工作了。
`成员变量` -- 组件的状态。我们将组件的数据封装成一个独立的类,并在 `ngOnInit` 进行创建一个实例。
```ts
this.stock = new Stock("Test Stock Company", "TSC", 86, 90);
```> 数据之间有依赖关系,如何实现像 vue 中的计算属性?
### 组件的数据绑定
使用`{{}}`插值语法绑定标签的内容,即设置 `textContent` 属性。
`[]` 绑定 DOM 属性,`[class]="stock.isPositiveChange?'positive':'negative'"`,这样绑定的类不会覆盖原来的类,而是追加一个类。
`{{}}` 、`[]` 是组件到 UI 模板的单向绑定。单向绑定:从组件中读取状态,更新 UI,往往在纯展示性的组件中常见。
> HTML 属性 和 DOM 属性的区别?
DOM 属性和 HTML 属性有交集,比如 HTML ID 直接映射到 DOM 的 ID,但有的属性只存在两者之一,比如 `defaultValue` 只存在 input DOM 中。
**HTML 属性往往做 DOM 元素属性的的初始化,初始化之后,HTML 的渲染效果,是 DOM 控制的**。
> ng 绑定是 DOM 属性,而不是 HTML 属性。
`` 这个 html input 元素,会初始化一个 DOM 元素,即 input DOM 的 value 为 foo. 在输入 `bar`,
`input.getAttribute('value')` 的值为 foo,是 HTML 中的初始化值,而 `input.value` 会返回 `bar`,这是 DOM 元素中的值,当前值。
### 组件处理事件
事件是组件和用户交互的主要方式,组件处理事件必不可少。事件处理语法:
```ts
eventName = "handleCall([$event[,otherParams]])";
```用 `$event` 获取到**事件对象**,`$` 不能省略,事件参数是可选的,还可添加其他参数,然后在类中实现该函数。
> 容易犯的错误是**不加括号**。
```html
{{stock.isFavorite?'已经购入':"购入"}}
```
```ts
toggleFavorite(event, param) {
console.log('用户点击了', event);
console.log('函数参数', param);
this.stock.isFavorite = !this.stock.isFavorite;
}
```> 如何阻止默认行为?
```ts
event.preventDefault();
```同样,阻止事件冒泡 `event.stopPropagation();`
### 总结
学习了组件的组织方式、插值语法、DOM 属性绑定和事件绑定。
## 表单处理
表单是用户向服务器发生数据的主要方式。
表单接收用户输入,UI 更新,同时希望组件内部的数据也跟着变化,就要实现双向绑定。ng 实现双向绑定的方式有两种:① 事件处理 ② 内置指令 `ngModel`
1. 事件监听 + 属性绑定
思路是监听表单事件,获取到该元素,然后把用该元素的值更新组件中的状态。
```html
```
> 监听 input,获取用户输入,输入值更新组件状态,而组件状态又绑定到模板上,从而实现数据同步。
**事件实现双向绑定的缺点:**
- 需要准确记忆每个表单控件的属性;
- 记忆表单事件;不同的表单控件具有不同的属性和事件,无疑是一种记忆负担,为了避免以上缺点,就有了 ngModel 指令。
2. 内置指令 ngModel
ngModel 是 input 事件绑定和 value 属性绑定的抽象,使得表单使用起来更加容易。
在`主模块 app.modules.ts` 中导入 `FormsModules` 模块,
```ts
import { FormsModule } from "@angular/forms";
```使用模块:
```ts
imports: [
FormsModule,
],
```修改模板:
```html
```
三个改变:
- 在表单控件上设置 `name` 属性,或者 `[ngModelOptions]="{standalone: true}"`
- 数据绑定 `[ngModel]="stock.name"`,指定了从组件中获取的成员变量
- 事件绑定 `(ngModelChange)="stock.name = $event"`,`$event` 是用户的输入值,必须是 `$event`。可能需要在修改成员变量之前做一些其他操作,比如`请求服务器数据`,可以把事件绑定的函数写到组件类里面:
```ts
change(name): void {
// do something else
this.stock.name = name;
}
````ngModel` 香蕉箱写法:
```html
```
> 香蕉箱语法是`[]`包裹`()`,这点容易混淆。ng 团队认为 `()`像两条香蕉,`[]`像箱子,`[()]`好像香蕉放在箱子里,故称为香蕉箱语法(banana-in-a-box)。
> 何时使用两个绑定的展开语法?
香蕉语法只能绑定数据,不能在绑定数据之前做额外的操作,比如想要把用户输入转为大小,就得使用展开语法了。