最近在看angular4,随手记的一些angular的随笔。javascript
新上手或者准备学angular的能够用做参考,第一次写博客,笔记不算完整,若老司机发现有不足指出请指出。css
技术交流群:513590751html
组件java
是Angular应用的基本构件块、能够把一个组件理解为一段带有业务逻辑和数据的html指令 详细指令速查web
容许向html添加自定义行为模块typescript
用来将应用中不一样的部分组成一个Angular框架能够理解的单元
服务编程
用来封装可重用的业务逻辑
#varName
用来元数据附加到typescript的类上面 从而让angular把这个类识别为组件 ## selecter:css的选择器,标志能够根据该选择器做为html标签 ## templateUrl:指定了html文件做为组件的模版 ## styleUrls:指定了组件模版中的样式
控制器是指被@component()装饰的类 包含与模版相关的全部的属性与方法 与页面相关的大部分逻辑都是编写在控制器里面
用@NgModule装饰器生成一个模块 ## 用declarations声明了模块中有什么东西(只能声明组件、指令和管道) ## 用imports声明了模块依赖的其余模块 ## 用providers声明模块中提供什么服务(此处只能声明服务) ## 用bootstrap声明了模块的主组件 ## 在模块中声明服务,在全部组件中均可以使用,在组件中声明服务,只能在组件中使用(每一个想要被注入的服务都须要在服务提供其中声明)
建立:ng new my-app 启动:ng serve [--open] --open:在浏览器打开 --routing:生成一个带route的项目 生成组件:ng g component [componentName] 生成服务:ng g service [serviceName] 生成管道:ng g pipe [pipeName] 生成指令:ng g directive [directiveName]
名称 | 简介 |
---|---|
Routes | 路由配置,保存着哪一个URL对应展现哪一个组件,以及在哪一个RouterOutlet中展现组件 |
Routerlet | 在HTML中标记路由内容呈现位置的占位符指令 |
Router | 负责在运行时执行路由的对象,能够经过调用其navigate()和navigateByUrl()方法来导航到一个指定的路由 |
RouterLink | 在HTML中声明路由导航用的指令 |
ActivatedRoute | 当前激活的路由对象,保存着当前路由的信息,如路由地址,路由参数等 |
path:路由URL component:路由对应的组件 {path:"**",component:Page404Component} //404页面,放到全部路由的最后 children:[{path:"aaa",component:AaaComponent}]子路由 redirectTo:重定向的URL pathMatch:指定匹配方式,匹配path中的 '',(full彻底匹配,prefix匹配前缀) loadChildren:延迟加载 canActivate:[class] //此处调用的类须要在providers里面声明,该类实现了CanActivate类 implements CanActivate canDeactivate:[class] //此处调用的类须要在providers里面声明,该类实现了CanDeactivate类 implements CanDeactivate<component> resolve:{param1:value1,params2:value2} //此处调用的类须要在providers里面声明,该类实现了Resolve类 implements Resolve<component>
传参: 方式1:/product?id=1&name=2 方式2:{path:/product/:id} => /product/1 方式3:{path:/product,component:ProductComponent,data:[{flag:true}]} 取值:ActivatedRoute.queryParams[id] //适用于方式1 ActivatedRoute.params[id] //适用于方式2 ActivatedRoute.data[0][flag] //适用于方式3
export class ProductComponent implements OnInit { private name; private id; constructor(private activatedRoute: ActivatedRoute) { } ngOnInit() { // 订阅方式 若是会有组件调用自己的状况就使用订阅方式 this.activatedRoute.params.subscribe((params: Params ) => this.id = params["id"] ); // 快照方式 this.name = this.activatedRoute.snapshot.queryParams["name"]; this.id = this.activatedRoute.snapshot.params["id"]; } }
<router-outlet></router-outlet> <router-outlet name="aux"></router-outlet> {path:"xxx",component:XxxComponent,outlet:"aux"} {path:"yyy",component:YyyComponent,outlet:"aux"} <a [routerLink]="[{outlets:{aux:null}}]">xxx</a> <a [routerLink]="[{outlets:{primary:'home',aux:'yyy'}}]">yyy</a> primary:控制主路由
CanActivate:处理导航到某路由的状况。 CanDeactivate:处理当前路由离开的状况。 Resolve:在路由激活以前获取路由数据。
在providers中注册接口 在须要引用的类的构造方法的参数中注入 constructor(private params1:Params){} 当使用同一个接口不一样的实现类时,在providers中声明providers: [{ provide: Params, useClass: AnotherParams }] 使用工厂类肯定使用哪一个类时,在providers中声明providers:[{ provide: Params, useFactory: () => { let depClass = new DepClass(); // 此处工厂方法和DepClass类耦合 let isLogin = Math.random() > 0.5; // 可能还依赖一个外部的变量来判断须要建立哪一个类 //在这里返回要使用的类型 注意:工厂方法只会在建立第一个须要注入的对象的时候被调用一次 } },DepClass] // 为工厂方法解耦合 使用deps属性来声明工厂方法依赖的类和变量的provide属性,在providers中声明providers:[{ provide: Params, useFactory: (depClass:DepClass,isLogin) => { //在这里返回要使用的类型 }, deps: [DepClass,"IS_LOGIN_ENV"] },DepClass,{ provide:"IS_LOGIN_ENV", useValue:false }] useValue的值能够是基本类型,也能够是对象类型 angular会吧工厂方法依赖的DepClass类注入到工厂方法
<h1>{{productTitle}}</h1>
<img [src]="imgUrl" /> <img src="{{imgUrl}}" />
<button (click)="clickEvent($event)">绑定事件</button>
事件中使用 event.target.value 获取的值是html元素的dom属性(dom属性的值是会发生变化的)
使用 event.target.getAttribute("value") 获取的值是html元素的初始值(html属性是不会发生变化的) <div class="aaa bbb" [class]="ccc">这种方式会替换原class属性的值</div> <div class="aaa bbb" [class.ccc]="true">这种方式不会替换原class属性的值</div> <div [ngClass]="{aaa:isTrue,bbb:isShow}">这种方式能够控制多个属性的显示</div>
<div [(ngModel)]="name">双向数据绑定</div>
{{name | filter}} eg:{{birthday | data}}// 将生日转化成日期格式 eg:{{birthday | data:'yyyy-MM-dd HH:mm:ss'}}// 将生日转化成指定日期格式
在项目中生成一个管道,而后在管道类的transform方法中对值进行操做。
export class PipeName implements PipeTransform { transform(value: any, arg: any): any { // value 是要在管道作处理的值 // arg 是管道后面跟着的参数 } }
一、在项目模块中引入ReactiveFormsModule模块 二、在组件中声明FormControl类型的字段 eg:formControlName 三、在页面中控件上声明[formControl]="formControlName" 四、在组件中订阅formControlName的valueChanges事件 eg:this.formControlName.valueChanges.subscribe(value => this.keyword = value);
在须要注入的属性上用@Input注解 在父组件中用[propName]="value"来赋值
在子组件属性上用@Output解属性类型为EventEmitter<DataType>类型 @Output() prop:EventEmitter<DataType> = new EventEmitter(); 用 prop.emit(dataTypeObj) 在父组件中声明dataTypeObj:DataType = DataType();//用来存放子组件Output出来的属性 在父组件引用子组件的标签上用事件订阅来订阅自组建发射的事件 用<child-comp (prop)="propHandler($event);"></child-comp> // 监控的事件名 prop 和@Output中的参数一致,不传参时默认和属性名一致 在父组件中声明 propHandler(event:DataType){ // 把子组件Output出来的属性赋值到父组件的属性上 this.dataTypeObj = event; }
两个子组件,经过@Output数据到父组件和@Input从父组件接收数据来实现组件间通信,父组件为中间人
想要使用这些钩子,须要先实现对应的接口 被调用一次的钩子 constructor(组件构造方法,调用该方法时,组件的输入属性没有值) ngOnInit(初始化组件或指令,调用该方法时,OnChanges方法已被调用,组件的输入属性有值) ngAfterContentInit(和angular的内容投影相关的) ngAfterViewInit(和angular的视图初始化和检查相关的,在此方法不可修改组件的属性) ngOnDestroy(组件销毁,在路由到其余组件时当前组件被销毁) 被调用屡次的钩子 ngOnChanges(父组件初始化或修改子组件的输入属性的值的时候被调用,若是一个方法没有输入属性,则该方法不会被调用) ngDoCheck(用来检测,在每一个angular的变动检测周期调用) ngAfterContentChecked(和angular的内容投影相关的) ngAfterViewChecked(和angular的视图初始化和检查相关的,在此方法不可修改组件的属性) 调用顺序: constructor、ngOnChanges、ngOnInit、ngDoCheck、ngAfterContentInit、ngAfterContentChecked、ngAfterViewInit、ngAfterViewChecked、ngAfterContentChecked、ngAfterViewChecked
#在父组件的模块中调用子组件的方法 一、在子组件上声明模版变量 #childName 二、在父组件中声明一个类型为 ChildeComponent 的变量 child 三、用 @ViewChild("childName") 注解声明的变量 child 四、在代码块中用 this.child.methodName(args) 来调用子组件的方法 #在父组件的模版中调用子组件的方法 一、在子组件上声明模版变量 #childName 二、在父组件的模版中绑定事件 (click)="childName.methodName('args')"
#父组件 <div> <child-comp> <div class="header">这是头部</div> <div class="footer">这是底部</div> </child-comp> </div> #子组件 <div> <ng-content select=".header"></ng-content> <ng-content select=".footer"></ng-content> </div> 定义单个投影点时能够不写class属性和select属性
表单的数据模型是经过组件模版中的相关指令来定义的,由于使用这种方式定义表单的数据模型时,咱们会受限与HTML的语法,因此,末班驱动方式只是用于一些简单的场景
NgForm NgModel NgModelGroup 用#myForm来声明表单的模版变量,在表单的onSubmit="onSubmit(myForm.value,myForm.valid)"来传入表单的值和表单是否经过验证
@Directive({ selecter: "[dirName]", // 在html上做为属性使用 providers: [{provide: NG_VALIDATORS, useValue: mobileValidator, multi: true}] // mobileValidator是已经声明的验证器 })
使用响应式表单时,经过编写TypeScrtipt代码而不是HTML代码来建立一个底层的数据模型,在这个模型定义好之后,使用一些特定的指令,将模版上的HTML元素与底层的数据模型链接在一块儿
FormControl userinfo: FormControl = new FormControl("aaa"); FormGroup FormGroup是多个FormControl的集合 FormArray
方式1、 formModel: FormGroup = new FormGroup({ username: new FormControl("初始值"), password: new FormControl(), email: new FormArray([ "a", "b" ]) }); 方式2、 constructor(fb: FormBuilder){ this.formModel = fb.group({ username: ["初始值", Validators.required], // 第二个参数是校验器,能够传一个数组,第三个参数是异步校验器 password: [""], email: fb.array([ "a", "b" ]) }); } <!-- 使用 novalidator 阻止浏览器默认的表单验证如:(required) --> <form [formGroup]="formModel" novalidator> <!-- required 验证表单是否为空 --> <input type="text" ngModel required formControlName="username"/> <!-- 第一个参数是校验器返回的错误对象的key,第二个参数是校验的字段 --> <div [hidden]="formModel.hasError('required','username')">用户名不能为空</div> <input type="text" formControlName="password"/> <div *ngFor="let e of email;let i = index;" formArrayName="email"> <input type="text" [formControlName]="i"/> </div> </form>
funcName(control: AbstractControl) {[key: string]: any} { return null; } eg: mobileValidator(control: FormControl) any { let valid = true; return valid ? null : {mobile : true}; } constructor(fb: FormBuilder){ this.formModel = fb.group({ mobile: ["", this.mobileValidator] }); } onSubmit() { let isValid:boolean = this.formModel.get("username").valid; // 获取字段是否经过验证 let error:any = this.formModel.get("username").errors; //获取字段未经过验证的错误信息 this.formModel.valid; // 用来判断表单是否合法 }
异步校验器做为字段构造的第三个参数传入 funcName(control: AbstractControl) {[key: string]: any} { // 返回的对象用Observable.of方法包裹,delay延迟5s return Observable.of({}).delay(5000); } eg: mobileAnsycValidator(control: FormControl) any { let valid = true; return Observable.of(valid ? null : {mobile : true}).delay(5000); } constructor(fb: FormBuilder){ this.formModel = fb.group({ mobile: ["", this.mobileValidator, this.mobileAnsycValidator] }); }
一、import Http from "@angular/http"; 二、在cunstructor方法中注入:cunstructor(http: Http) 三、使用this.http.get("url",data)获取数据,而且用.map(res => res.json())把获取到的数据转换成json格式 四、用Observable类型的变量接收数据 五、订阅Observable类型的变量,而且用obs.subscribe(data => this.product = data)来赋值给变量 proxy.conf.json配置 // 意指当前请求是以/api开头时,把请求转发到http://loacalhost:8000 { "/api": { "target": "http://loacalhost:8000" } } // 在package.json中配置 ng serve 命令添加参数 --proxy-config proxy.conf.json
import {Injectable} from '@angular/core'; import {Observable} from "rxjs/Observable"; @Injectable() export class WebSocketService { ws: WebSocket; constructor() { } // 根据传入的url建立一个websocket协议 createObservableScoket(url: string): Observable<any> { // 建立websocket服务 this.ws = new WebSocket(url); return new Observable(observer => { // 返回成功时执行的方法 this.ws.onmessage = event => observer.next(event.data); // 返回错误时执行的方法 this.ws.onerror = event => observer.error(event); // 关闭websocket流时执行的方法 this.ws.onclose = event => observer.complete(); }); } sendMessage(msg: string) { this.ws.send(msg); } }
export class SearchComponent implements OnInit { constructor(private wsService: WebSocketService) { } ngOnInit() { // 订阅websocket返回的值 this.wsService.createObservableScoket("ws://localhost:8085").subscribe( data => console.log(data), error => console.log(error), () => console.log("webSocket已结束!") ); } }