0%

9.Angular中的表单校验

1. 模板驱动表单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1. 需要引入FormsModule
import { FormsModule } from '@angular/forms';

2. 通过ngModel双向绑定属性,并设置校验规则
<input id="name" name="name" required minlength="4" appForbiddenName="bob" [(ngModel)]="name" />

3. 在html中设置错误提示
<div *ngIf="name.invalid && (name.dirty || name.touched)"class="alert alert-danger">
<div *ngIf="name.errors.required">
Name is required.
</div>
<div *ngIf="name.errors.minlength">
Name must be at least 4 characters long.
</div>
<div *ngIf="name.errors.forbiddenName">
Name cannot be Bob.
</div>
</div>

优缺点:
只有简单修改html就能完成表单数据绑定和验证
但当表单字段过多,会使HTML过于复杂

2. 响应式表单

优缺点:
解耦HTML,针对大表单数据,易于维护
代码编写比模板驱动表单复杂

阅读全文 »

8.Angular中的模块

1. 创建自定义模块

1
2
3
4
ng g module 路径

创建带路由的模块
ng g module 路径 --routing

2. 使用自定义模块

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
e.g:
1. 创建自定义模块
ng g module modules/user --routing

2. 创建模块下子组件
ng g component modules/user/components/address

3. 创建模块根组件
ng g component modules/user

4. 在自定义模块中暴露出想在根组件中使用的子组件
@NgModule({
declarations: [模块下的子组件],
imports: [
CommonModule,
LiveChannelRoutingModule
],
exports:[想暴露出去的子组件]
})

5. 在根模块中导入自定义模块,即在app.module.ts文件中修改
import { 自定义模块 } from './live-channel/live-channel.module';

@NgModule({
declarations: [
AppComponent,
HeaderComponent,
FooterComponent,
MenuComponent
],
imports: [
BrowserModule,
AppRoutingModule,
自定义模块,
],
providers: [],
bootstrap: [AppComponent]
})

7.Angular中的路由

1. 路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 路由: 即根据不同的url地址,动态的让根组件挂载其他组件,来实现一个单页面应用程序

- 带路由模块的项目比起不带路由项目中:
1. 在app目录下多一个app-routing.modules.ts,即路由的配置文件
2. 在app.modules.ts中引入了路由模块,并注入
import {AppRoutingModule} from './app-routing.module';

@NgModule({
...
imports:[
BrowserModule,
AppRoutingModule
]
...
})
3.在根组件的html中新增了标签
<router-outlet></router-outlet>

2. 路由的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1. 需要在路由的配置文件app-routing.modules.ts中,引入使用路由的组件
import {xxxComponent} from '../components/xxx';

2. 配置路由
const routes: Routes = [
{path:'xxx',component:xxxComponenet},
...
{path:'**',redirectTo:'xxxPath' | component:xxxComponenet}
]

path: url地址
component: 访问对应path,需要挂载的组件

path:'**',即任意路由,一般用于匹配其他值或默认值(类似switch中的default)
redirectTo: 跳转的路由(也可配置component,挂载对应的路由,一般还是跳转)

3. 组件模板中使用路由(使用routerLink),并配置router-outlet来显示动态加载的路由组件视图
// routerLink即路由path,可配置为动态(即使用 [] ),也可为静态
<a [routeLink]='/home'>首页</a>
<router-outlet></router-outlet>

4. 路由选中状态
//给路由的标签加上routerLinkActive属性,属性值即class名,在css样式文件中设置样式即可
<a [routeLink]='/home' routerLinkActive="active">首页</a>

3. 路由跳转传值

阅读全文 »

5.Angular中的生命周期函数

1. Angular中的生命周期函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
生命周期函数执行顺序,从上到下

1. ngOnChanges(): 父子组件互相传值时会触发,首次触发一定在ngOnInit()之前

2. ngOnInit(): 初始化组件以及指令(此时dom并未完全加载),一般将请求数据的操作放到这里

3. ngDoCheck(): 可以做一些自定义操作,来监测数据是否变化

4. ngAfterContentInit(): 组件渲染完成后调用

5. ngAfterContentChecked(): 在每次组件渲染完成后,可以做一些自定义操作

6. ngAfterViewInit(): 视图加载完成,一般在这里进行dom操作

7. ngAfterViewChecked(): 在每次视图加载完成后,可以做一些自定义操作

8. ngOnDestroy(): 组件销毁时触发

构造方法不属于生命周期函数,在构造方法中,除了对成员变量初始化之外,其他什么都不应该做

15.Rxjs中并行处理多个Observable

1. forkJoin

1
2
3
4
5
6
7
let o1 = new Observable();
let o2 = new Observable();
let o3 = new Observable();

forkJoin([o1,o2,o3]).subscribe([r1,r2,r3]=>{
...
})

forkJoin:当每个Observable都完成时,才会触发subscribe方法,即每个Observable对象内,都需要有observer.complete()

2. combineLatest

1
2
3
4
5
6
7
8
let o1 = new Observable();
let o2 = new Observable();
let o3 = new Observable();

combineLatest([o1,o2,o3]).subscribe([r1,r2,r3]=>{
...
})

阅读全文 »

14.Angular中的指令

1. 指令类型

Angular 中有三种类型的指令

  1. 组件 — 拥有模板的指令
  2. 结构型指令 — 通过添加和移除 DOM 元素改变 DOM 布局的指令
  3. 属性型指令 — 改变元素、组件或其它指令的外观和行为的指令

2. 属性指令

创建指令: ng generate directive xxxxx

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
import { Directive } from '@angular/core';

@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {

@Input() highlightColor: string;

constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = this.highlightColor;
}

@HostListener('mouseenter') onMouseEnter() {
this.highlight('yellow');
}

@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);
}

}

el: ElementRef: ElementRef 通过其 nativeElement 属性给你了直接访问宿主 DOM 元素的能力。

@Input(): 可以接收传递给指令的参数,不命名,默认和变量名称一样,也可以使用别名,即写成其他名字,如指令名,直接通过 [appHighlight]='xxxx',接收参数,并且可以写多个,来接收多个传入的参数

@HostListener(): 让你订阅某个属性型指令所在的宿主 DOM 元素的事件
阅读全文 »

13.Angular中的打包部署

1.打包指令

1
2
3
4
5
ng build --base-href xx --prod

--base-href:指定在生成和识别URL时应保留的URL前缀。

--prod: 指定生产模式,会压缩文件并去掉代码中的console

2.实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   # /lv/ 是nginx中监听的path
- 打包,并指定前缀
ng build --base-href /lv/ --aot --prod

- nginx中配置 location需要与ng打包的前缀一致
location ^~ /lv {
alias D:/IdeaProject/ETS-Cloud_LiveService/front/live-manager/dist/live-manager; # 这是angular生成的dist文件夹存放的位置
index index.html index.htm;
try_files $uri $uri/ /index.html =404; # 注意此句,一定要加上。否则配置的子路由等无法使用
}


# 配置webSocket连接
location ^~ /live/websocket {
proxy_pass http://live-microservice;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 1000m;
proxy_set_header Upgrade $http_upgrade; #ws配置
proxy_set_header Connection "upgrade"; #ws配置
}

3.angular中编码方式获取APP-BASE-HREF

阅读全文 »

11.路由守卫-Guard

1.Guard

1
2
3
4
5
6
有四种类型:
1.canActivate: 控制是否允许进入路由
2.canActivateChild: 等同于canActivate,只不过针对是所有子路由
3.canDeactivate: 控制是否允许离开路由
4.canLoad: 控制是否允许延迟加载整个模块

属性名 接口名
canActivate CanActivate
canActivateChild CanActivateChild
canDeactivate CanDeactivate
canLoad CanLoad

canDeactivate 需要指明具体的组件类名以外,其他接口只是将首字母大写而已。假定需要一个某个角色才能访问某些路由,就需要一个 CanActivate 守卫类。

2. 如何使用

阅读全文 »

10.Angular中的拦截器

1. 拦截器

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
1.需要实现HttpInterceptor接口
@Injectable()
export class SignInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
...
}
}


2.暴露拦截器链
import { HTTP_INTERCEPTORS } from '@angular/common/http';

import {SignInterceptor} from './sign.interceptor';

//multi:true 表示有多个拦截器
export const httpInterceptorProviders = [
{provide: HTTP_INTERCEPTORS, useClass: SignInterceptor, multi: true},
];

3.在模块中使用拦截器
@NgModule({
declarations: [...],
imports: [...],
providers: [httpInterceptorProviders]
})

4.Angular中的Dom操作以及父子组件通讯

1. 组件中获取Dom对象

1
2
3
组件中的ngOnInit()方法,是组件和指令初始化完成,并不是真正的dom加载完成  

组件中还有一个ngAfterViewInit()方法,这个是视图加载完成,因此建议把dom操作都放在这个方法内

2. 通过@ViewChild装饰器获取Dom对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1.需要在html中给dom起一个名字,e.g:
<div #myBox></div>

2.在组件中引入viewChild,e.g:
import {Component,OnInit,ViewChild} from '@angular/core';

3.通过@ViewChild装饰器获取Dom对象,通过类的成员变量,e.g:
export classs xxx implements OnInit {

@ViewChild("myBox") myBox:any;

constructor(){
...
}
}
4.在生命周期函数ngAfterViewInit中操作Dom对象,e.g:
//nativeElement才是dom对象
this.myBox.nativeElement

3. 通过@ViewChild获取子组件

阅读全文 »