最近在看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已結束!") ); } }