Angular学习之路

Posted by Liber Sun on June 19, 2020

关键概念

模块

NgModule是模块,可以将组件及其相关代码(如服务)关联在一起,形成功能单元。每个Angular项目都有一个根模块 AppModule

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ Logger ],
  declarations: [ AppComponent ],
  exports:      [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
  • imports,导入本模块需要的其他模块
  • providers, 需要使用的Service
  • declarations,引入需要的components、directives和pipes
  • exports,对外导出可用的组件
  • boostrap,确定根组件。

组件

Component是组件,组件可以理解为一个类,包括其中的属性(数据)和方法(逻辑),并与一个HTML和CSS模板进行关联。

双向绑定

利用Angular提供的标记(Markup),能够将组件中的数据和DOM连接在一起。

管道

Pipes管道, 能够将数据进行转换以增强用户体验,Angular提供了一些预定义的管道

  • async
  • currency 转为金额
  • date 转为日期
  • number 转为数字
  • json 转为json字符串
  • lowercase 小写
  • uppercase 大写
  • percent 转为百分比
  • slice:fron:to 切割
  • titlecase 将每个单词的第一个字母大写

服务与DI

服务是与特定视图无关,但希望共享方法和数据的类,即服务类。有了服务类,组件就不用从服务器获取数据、验证用户输入或直接把日志写到控制台,而是会把这些任务委托给服务。

引入服务,有三种方法,一种是直接在NgModule中利用providers,另一种实在组件层次利用providers,还有一种是在服务本身通过Injectable,

@NgModule({
  providers: [
   BackendService,
   Logger
 ],
 ...
})

@Component({
  ...
  providers:[]
})

@Injectable({
  providedIn: 'root',
})

路由

Router,根据路由动态渲染页面,实现按需加载。本质上实现了 Path组件 的关联关系。

Angular自带的库说明

Angular 会作为一组 JavaScript 模块进行加载,你可以把它们看成库模块。每个Angular 库的名称都带有 @angular 前缀。 使用 npm 包管理器安装 Angular 的库, 并使用 JavaScript 的 import 语句导入其中的各个部分。

import { Component } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';//ngFor,ngIf
import { FormsModule } from '@angular/forms';  //[(ngModel)]
import { ActivatedRoute } from '@angular/router';

小讲堂

子组件获取父组件传递来的数据,需要引入 import { Input } from "@angular/core"; , 然后在类的属性中通过注解 @Input() 属性名:属性类型 进行声明。

  • *ngFor
  • *ngIf
  • 插值
  • 属性绑定 [searchValue],子组件在使用时需要使用 @Input() 注解,当子组件希望触发一个事情,需要引入 @Output() notify=new EventEmitter() , 然后使用 notify.emit() , 然后父子件需要响应这个 (notify)='fatherHandler'
  • 事件绑定 (click)
  • 双向绑定 [(searchValue)]
  • #search 模板引用变量, 将当前HTML元素的值赋值与search,可以理解为起名字。 然后在组件中可以用过 @ViewChild('search') serach:ElementRef 获取该元素,进行DOM操作,或者调用组件方法。
content="<h1>haha</h1>" #动态HTML

<span [innerHTML='content']></span>
<span [ngSwitch]="orderStatus">
  <p *ngSwitchCase="1">已支付</p>
  <p *ngSwitchCase="2">已发货</p>
  <p *ngSwitchCase="3">已收货</p>
  <p *ngSwitchDefault>未知</p>
</span>

Angular引入第三方库

推荐使用 ng add xxx包 ,引入Angular的相关库,这些Angular相关的库往往提供了较好的 schematic ,可以自动导入相关的类库。

由于Angular依赖于Typescrit,如果引入的库不存在 *.d.ts 文件,需要额外关联@/types/{lib_name}包。查看是否支持ts,可使用网站TypeSearch如:

npm install d3 --save
npm install @types/d3 --save-dev #注意是开发环境

此时,直接通过 import 导入即可。而不存在 @/types 是可能出现的, 需要在 src/typings.d.ts 文件中或者在各自组件文件中添加类库声明信息:

declare const G2: any;

将某个库导入全局范围

如果对应的包没有使用 import export ,即无npm包的存在的形式的话,及存在原生的的方式的话,可以使用 angular.json 的添加方法,或者更为粗暴的方式是直接在 html 中引入。

在angular.json文件中,将关联的脚本添加到 script 数组中, 若依赖于 css静态资源 ,采用同样的操作。

"scripts": [
  "node_modules/jquery/dist/jquery.slim.js",
  "node_modules/popper.js/dist/umd/popper.js",
  "node_modules/bootstrap/dist/js/bootstrap.js"
],
"styles": [
  "node_modules/bootstrap/dist/css/bootstrap.css",
  "src/styles.css"
],
"assets": [
  "src/favicon.ico",
  "src/assets"
],
  1. 注意如果在全局范围内进行了导入,就不需要在Typescript代码中使用 import * as $ from 'jquery';
  2. 注意这种方式会将整个脚本导入,可以借鉴 LazyService 进行延迟加载。
  3. 注意这种方式虽然可以直接使用第三方库,但是注意到还是没有解决ts的问题,因此仍然要进行 declare const G2: any;

生命周期

  constructor() {
    console.log("除了使用简单的值对局部变量进行初始化之外,什么都不应该做");
  }
  ngOnInit() {
    console.log("请求数据一般放在这个里面");
  }



  ionViewWillEnter() {
    console.log("顾名思义,当将要进入页面时触发");
  }

  ionViewDidEnter() {
    console.log("每次都执行");
  }

  async ngAfterViewInit() {
    console.log("执行一次");
  }

  ionViewWillLeave() {
    console.log("当将要从页面离开时触发");
  }
  ionViewDidLeave() {
    console.log("离开页面时触发");
  }

创建模块和组件的逻辑

先模块,再组件,最后服务。

ng g module module/user --routing # --routing 能添加路由模块
ng g component module/user
ng g service module/user/services/common