概览
- 服务器端的socket和客户端的服务中的socket保持长连接,进行数据交换;
- 客户端中的服务(socket)作为”被观察者”,客户端中的组件作为观察者;
- 被观察者通过依赖注入,被注入到组件中;
组件订阅socket产生的流,当流发生变化时,组件就会产生相应的事务。
websocket.ts
|
|
component.html
|
|
组件订阅socket产生的流,当流发生变化时,组件就会产生相应的事务。
|
|
|
|
生成指令命令行:ng g directive directiveName
|
|
|
|
|
|
|
|
在Angular中,标准表单会被自动托管,常规的操作无效。如果希望使用原始表单,只需要在form标签内加上ngNoForm指令即可;
#myForm=”ngForm”获取表单对象,myForm.value获取表单的值,取值形式:
(ngSubmit)=”onSubmit(myform.value)”代替了默认的submit
只能在HTML中操作数据模型,不能在ts中操作
在ngForm上使用双向绑定时,不需要像以往那样[(ngModel)]=”user.name”,改写为:直接在标签中加入ngModel指令,同时指定name属性:name=”username”
如果要在ngmodel上使用组件模板变量,#username=”ngModel”,取值形式:
ngForm=>隐式创建FormGroup
ngModel=>隐式创建FormControl
ngModelGroup=>隐式创建FormGroup(嵌入结构,用于将一些字段更好地组织在一起,加入指定的对象中)
模板式表单的写法:
|
|
响应式表单不可以使用模板变量,如:#myForm,只能在ts中操作数据模型
FormControl
|
|
FormGroup
|
|
FormArray:创建一个可变长度子集
|
|
响应式表单的写法:
|
|
|
|
|
|
从标准格式可以看出,校验之后返回的对象为null或者一个key为字符串的对象
|
|
|
|
对于单独的FormControl检验
|
|
对于放在FormGroup内部的FormControl的校验
|
|
通过代码模拟http请求处理
|
|
注意方法的第一个参数不是校验器的名称,而是校验器返回来的对象的key,即:
在④中,如果发生错误,那么将会获取到返回的“错误提示信息”。
|
|
|
|
touched/untouched:字段是否获取过焦点,如果获取过则:true/false,否则相反;
|
|
pristine/dirty:如果一个值未被修改过,则:true/false,否则相反;
|
|
pending:当一个字段正处于异步校验中时,该字段为true
Angular的http服务返回的是Observable(可观察数据流),通过订阅来获取可用数据。
订阅方式有:手动订阅(subscript)、异步管道订阅(async)
|
|
|
|
|
|
|
|
在定义https请求时,需要添加headers的时候,如下:
有些时候Angular启动的端口地址和服务器端口地址不一致,导致所有的http请求失败。我们需要做端口转发。
|
|
即:将以”/api”开头的请求地址转发到”http://localhost:8080“
修改package.json的start项
|
|
修改请求的地址
|
|
consttructor -> ngOnChanges -> ngOnInit -> ngDoCheck ->
ngAfterContentInit -> ngAfterContentChecked -> ngAfterViewInit ->
ngAfterViewChecked -> ngOnDestroy
|
|
无论val如何变化,’hello’在内存中的地址始终保持不变。字符串是不可变对象。
|
|
|
|
|
|
|
|
|
|
以上代码结果表现为:
虽然修改可变对象不会触发ngOnChanges钩子,但是子组件上的值已然发生了变化。这是由于Angular的变更检测机制仍然不活了组件中每个对象的属性的变化。
在Angular2中,变更检测机制是由zone.js提供的,保证组件的属性的变化和页面的变化是同步的。
变更检测机制仅仅是将组件属性的改变反应到模块上,它并不会去改变组件属性的值。
|
|
子组件
|
|
父组件
|
|
|
|
钩子调用顺序:①->②->③->④
|
|
子组件
父组件
|
|
子组件
在投影内容组装完成之后调用、检测之后调用;
执行顺序:ngAfterContentInit -> ngAfterContentChecked -> ngAfterContentInit -> ngAfterContentChecked -> ngAfterViewInit
与ngAfterView的钩子不同,在ngAfterContent的钩子中可以改变属性的值
组件初始化
①constructor
②ngOnChanges
③ngOnInit
④ngDoCheck
⑤ngAfterContentInit
⑥ngAfterContentChecked
⑦ngAfterViewInit
⑧ngAfterViewChecked
⑨ngOnDestory
组件销毁
⑨ngOnDestory
变更检测
②ngOnChanges
④ngDoCheck
⑥ngAfterContentChecked
⑧ngAfterViewChecked
当通过路由激活一个组件(按先后顺序):
组件初始工作:
启动constructor,提供所需实例化的对象
如果有输入属性,启动ngOnChanges检测输入属性的变更
启动ngOnInit,初始化一般数据
启动ngDoCheck,进行一次变更检测
开始组装组件:
当组件中的投影内容被组装时,调用ngAfterContentInit
启动ngAfterContentChecked,对投影内容检测
当整个组件被组装时,调用ngAfterViewInit
启动ngAfterViewChecked,对整个组件检测
组件变更:
当有事件发生(用户操作),启动ngDoCheck进行变更检测
处理变更,如果需要更新组件,启动ngAfterContentChecked、ngAfterViewChecked;如果输入属性发生变化,启动ngOnChanges
路由事件发生,启动ngOnDestory销毁组建,从头开始初始化一个组件;
父组件:
|
|
|
|
子组件
|
|
|
|
子组件:对外发射数据
|
|
|
|
|
|
在Angular中,捕获子组件中发射的事件,和捕获原生的DOM事件是一样的操作。
第一步:Angular在应用启动时,会生成一个应用级的注入器,将主模块和引用模块中的提供器(provide)全部注入到其中;
第二步:Angular创建启动模块指定的主组件(AppComponent),同时应用级的注入器会为主组件创建一个组件级的注入器。
并将主组件中声明的提供器注入到组件级的注入其中;
第三步:在主组件中的子组件被创建时,主组件的注入器会为被激活的子组件创建一个组件级的注入器;
并将子组件中的提供器注入其中;
Angular只提供在构造函数中注入的方式来创建服务;
|
|
除了常用的在构造函数的参数直接声明服务以外,还可以手动调用注入器获取需要的服务
|
|
|
|
|
|
在input事件发生的时候,在控制台中可以看到①打印的值与文本框保持一致,而②始终是默认的value值;
这是因为HTML属性指向的是初始值,而DOM属性指向的是当前值,且HTML属性不可变;
|
|
由于Angular使用的是DOM属性绑定,而DOM属性中没有colspan,故①中的写法会报错;
DOM属性发生变化时的流程
cli命令创建管道:ng g pipe pipeName
|
|
extraMultiple.ts
|
|
app.component.html
|
|
如果有多个过滤参数:
依赖注入和控制反转是一体两面,依赖注入是目的,控制反转是手段,终究实现代码的松耦合。
|
|
|
|
1.productService.ts
|
|
2.anthorProductService.ts
3.app.module.ts
4.product.component.html
使用在模块中声明的服务
使用在组件中的服务
在提供服务时,可能要根据不同的状态去初始化不同的服务实例,这时需要使用useFactory提供器来完成。
通过随机数模拟开发/生产状态来实例化不同的服务类:
|
|
该提供器方法常常结合useFactory使用
|
|
以上两点就是Angular实现“依赖注入”和“控制反转”的核心。
子路由相对于根路由的概念而来,示例:children:数组,配置路由相关信息
路由配置:
父组件:
概览:辅助路由可以有多个,根据“name”字段来匹配
|
|
|
|
如何使用?示例:
路由文件
|
|
守卫文件:loginGuard.ts
|
|
增加一个CanDeactivate守卫,表示是否可以离开该组件(常用来检查用户填写的信息是否已经保存):
实现守卫(实现CanDeactivate守卫接口)接口,unSaveGuard.ts文件中
注意事项:
|
|
将守卫加入到路由配置中
|
|
在NgModule中配置
|
|
该守卫常用在进入下一个组件之前,执行服务获取下一个组件需要用到的数据,并带入组件中。
所以该组件需要可以被注入,在写时需要加入@Injectable()标识
路由配置项改写
|
|
写productResolve.ts文件,提供ProductResolve函数
该class需要指定返回的参数的格式,即:
|
|
在组建中取值(采用订阅的方式)
|
|
|
|
此时,在app.module.ts 文件中可以看到已经被自动引入到 imports组中。
|
|
|
|
该写法等价于:
|
|
|
|
路由参数传递的方式有三种,分别是:
① 在查询参数中传递
② 在路径中传递
③ 在配置项中使用特定对象data传递
在查询参数中传递
传递方式:
|
|
接收方式:
|
|
在路径中设置参数
修改router中的配置:
|
|
修改Html中的RouterLink的写法:
|
|
Controller:
|
|
|
|
获取传进来的参数:
通过路由激活某一个组件之后,获取参数的方式有两种
参数快照,关键字:snapshot
|
|
参数订阅,关键字:subscribe
|
|
参数订阅与参数快照的使用场景:
当由HomeComponent进入到ProductComponent时,ProductComponent被激活,ngOnInit和constructor调用一次。
例如:Product组件内部产品间的切换,由于id是通过参数在ngOnInit中获取的:
①如果使用snapshot的方式,组件未被销毁,noOnInit不再执行,那么显示在外部的id值将不再更新,出现数据错误;
②处理方式,采用subscribe的方式,当参数发生变化,即可更新信息;