Angular 入门(真的只是入门)

前言

这个入口没有过多的言语,只会把平时做 Angular 开发中很常用到的一些东西整理出来,让你过目并轻松入门。

指令

指令即为 Angular 为我们封装好的一些模块。我们通过简单的调用就可以实现一些想要的功能。

NgIf 指令语法

*ngIf="condition"

<div *ngIf="isLoaded">加载完成</div>

*ngIf="condition; else elseTemplate"

<div *ngIf="isLoaded; else elseTemplate">加载完成</div>
<ng-template #elseTemplate>正在加载</ng-template>

*ngIf="condition; then thenTemplate; else elseTemplate"

<div *ngIf="isLoaded; then then thenTemplate; else elseTemplate"></div>
<ng-template #thenTemplate>加载完成</ng-template>
<ng-template #elseTemplate>正在加载</ng-template>

then thenTemplate 的作用其实就是把 *ngIf 满足条件时要显示的内容放到了 <ng-template> 模板标签中然后通过 then thenTemplate 来告诉 *ngIf 当条件满足时显示 thenTemplate 中的内容。

基于上面的实现,Angular 还提供了动态修改模板变量动态修改引用指向其他模板能力,具体用法可以查阅官方文档关于 NgIf 部分。

ngSwitch 指令语法

<div [ngSwitch]="switch_expression">
  <div *ngSwitchCase="match_expression_1">case_1</div>
  <div *ngSwitchCase="match_expression_1">case_2</div>
  <div *ngSwitchCase="match_expression_1">case_3</div>
  <div *ngSwitchDefault>case_4</div>
</div>

这个的用法跟 JS 中的 switch 差不多

<ng-container> 标签

如果使用结构指令时不想有多余的标签,那么可以使用 <ng-container> 标签作为宿主元素

<p>这里是一段文字
  <ng-container *ngIf="condition">
    这行文字有时显示,有时不显示
  </ng-container>
</p>

使用 <ng-container> 标签至少有三个好处:

  • 不会有多余的元素
  • 不会受到样式的影响
  • 不会改变现有的 HTML 结构

带索引的 *ngFor

<div *ngFor="let item of datas; let i=index">{{i + 1}} - {{item.name}}</div>

像 index 这样遍历为我们提供的可用变量还有

  • first:第一个
  • last:最后一个
  • even:偶数项
  • odd:奇数项

上面这四都是返回布尔值,再看个例子

<li *ngFor="let item of datas; let isFirst = first">{{item.name}} <span *ngIf="isFirst">first</span></li>

在 *ngFor 中除了像上面 let isFirst = first;这样保存变量外,我们还可以使用 as 来保存

<li *ngFor="let item of datas; first as isFirst ">{{item.name}} <span *ngIf="isFirst">first</span></li>

上面两种写法都可以。

样式相关

<!-- [ngStyle] -->
<div [ngStyle]="{'font-size': '24px'}">Hellow Word</div>
<div [ngStyle]="{'font-size.px': '24'}">Hellow Word</div>
<div [ngStyle]="objExp">Hellow Word</div>
<div [ngStyle]="{'font-size.px': true ? '24':'16'}">Hellow Word</div>

<!-- [ngClass] -->
<div [ngClass]="{'class1 class2': true}">Hellow Word</div>
<div [ngClass]="{'first': true, 'second': false}">Hellow Word</div>
<div [ngClass]="{true: 'first', false: 'second'}[true]">Hellow Word</div>

[ngStyle] 指令的值也可以是一个变量,变量为 key, value 的对象

表单

表单的实现有几种方式

模板变量

当页面的比较简单的时候,我们可以通过模板变量的方式来获取输入框的值

<input #box>
<button (click)="save(box.value)">保存</button>

模板驱动表单

这个比较好理解

<form #myForm="ngForm">
  <input name="name" type="text" [(ngModel)]="user.name">
  <input name="age" type="text" [(ngModel)]="user.age">
</form>
<button (click)="save(myForm)">保存</button>

我们给 save() 方法传入了这个 ngForm 的引用。我们可以通过个对象中的一些属性进行业务逻辑的处理,比如:整个表单的有效性(myForm.form.valid),获取表单项(myForm.form.controls["name"].valid)的有效性,获取表单项值组成的对象(myForm.value)。

上面的 myForm.form 其实也可以直接写成 myForm

表单中使用 [(ngModel)] 时,必须要定义 name 属性。官方有这么一句话:

在内部,Angular 创建了一些 FormControl,并把它们注册到 NgForm 指令,再将该指令附加到 <form> 标签。 注册每个 FormControl 时,使用 name 属性值作为键值。

路由

路由跳转的方式有两种,分别是指令和方法中调用 navigate 方法。

指令方式实现

如果只是简单的跳转无需在跳转时作额外的操作,那么我们可以像下面这样使用 Angular 为我们提供的指令来实现路由跳转。

无需要传参

<li class="hand" routerLinkActive="menu-active" [routerLink]="['/member']">会员通道</li>

需要传参

queryparams 方式:

<!-- 在页面中的 -->
<li class="hand" [routerlink]="['/postView']" [queryparams]="{id: 123}">会员通道</li>
<!-- 路由配置 -->
{ path: 'postView', component: BookViewComponent }
<!-- url 显示形式 -->
http://localhost:4200/postView?name=5c050a85978a09639f912669
<!-- 参数获取方式一(通过评阅) -->
this.activatedRoute.queryParamMap.subscribe((queryParams: ParamMap) => {
      const id = params.get('id');
    }
);
<!-- 参数获取方式 2(通过快照) -->
const id = this.activatedRoute.snapshot.queryParamMap.get('id')

非 queryparams 方式

<!-- 在页面中的 -->
<li class="hand" [routerlink]="['/postView', 123]">会员通道</li>
<!-- 路由配置 -->
{ path: 'postView/:id', component: BookViewComponent }
<!-- url 显示形式 -->
http://localhost:4200/postView/5c050a85978a09639f912669
<!-- 参数获取方式一(通过评阅) -->
this.activatedRoute.paramMap.subscribe((params: ParamMap) => {
      const id = params.get('id');
    }
);
<!-- 参数获取方式 2(通过快照) -->
const id = this.activatedRoute.snapshot.paramMap.get('id')

注意引入接口类,比如:ParamMap,不引入也可以就不使用此接口来限制参数的类型就可以了。

非指令方式

如果我们需要在跳转时作额外的操作,那么此时我们就可以使用函数调用的方式。

<!-- 引入 -->
import { Router } from '@angular/router'

<!-- 构造函数中注入 Router -->
constructor(private router: Router) { }

queryParams 方式

goDetail(id){
  // 添加额外操作 ......
  this.router.navigate(['/postView'], {
    queryParams: { id:id }
  })
}

非 queryParams 方式

goDetail(id){
  // 添加额外操作 ......
  this.router.navigate(['/postView',id])
}

在类中定义方法,然后在 html 中调用此方法 就可以了。

打包过大的问题

运行打包命令时,加上参数 --prod,把不用的包都删掉。

ng build --prod

这样 本来很大的 vendor.js 就会不见了,但有一个 main.xxx.js 文件还是比较大 700 多K。