{{expression}}
[target]="expression"
bind-target="expression"
複製代碼
單向從視圖到數據源css
(target)="statement"
on-target="statement"
複製代碼
雙向html
[(target)]="expression"
bindon-target="expression"
複製代碼
DOM property
的值能夠改變;HTML attribute
的值不能改變。
在 Angular
的世界中,attribute
惟一的做用是用來初始化元素和指令的狀態。
當進行數據綁定時,只是在與"元素和指令"的 "property
和事件"打交道,而 attribute
就徹底靠邊站了。express
若是忘了加方括號,Angular
會把這個表達式當作字符串常量看待,並用該字符串來初始化目標屬性。
下面這個例子把 HeroDetailComponent
的 prefix
屬性初始化爲固定的字符串"1+1",而不是模板表達式"2"。Angular
設置它,而後忘記它。json
<app-hero-detail prefix="1+1" [hero]="currentHero"></app-hero-detail>
複製代碼
做爲對比,[hero]
綁定是組件的 currentHero
屬性的活綁定,它會一直隨着更新。bootstrap
{{...}}
,先對雙花括號中的表達式求值,再把求值的結果轉換成字符串。 Angular
把這些插值表達式翻譯成了相應的屬性綁定。<p><img src="{{heroImageUrl}}"> is the <i>interpolated</i> image.</p>
<p><img [src]="heroImageUrl"> is the <i>property bound</i> image.</p>
複製代碼
script
標籤的 HTML
泄漏到瀏覽器中,兩者都只渲染沒有危害的內容。src/app/app.component.ts
evilTitle = 'Template <script>alert("evil never sleeps")</script>Syntax';
src/app/app.component.html
<p><span>"{{evilTitle}}" is the <i>interpolated</i> evil title.</span></p>
<p>"<span [innerHTML]="evilTitle"></span>" is the <i>property bound</i> evil title.</p>
複製代碼
attribute
綁定 property
,而不用字符串設置元素的attribute
。 ARIA
, SVG
和 table
中的 colspan/rowspan
等 attribute
。 它們是純粹的 attribute
,沒有對應的屬性可供綁定。 若是想寫出相似下面這樣的東西,就會暴露出痛點了:<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
複製代碼
會獲得這個錯誤:
Template parse errors: Can't bind to 'colspan' since it isn't a known native property
方括號中的部分不是元素的屬性名,而是由attr
前綴,一個點 (.)
和 attribute
的名字組成segmentfault
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
複製代碼
( [(...)] )
雙向綁定語法其實是屬性綁定和事件綁定的語法糖。數組
NgClass
,能夠同時添加或移除多個類。 把 ngClass
綁定到一個 key:value
形式的控制對象
(value
爲boolean
值)src/app/app.component.html
瀏覽器
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special</div>
複製代碼
src/app/app.component.ts
安全
currentClasses: {};
setCurrentClasses() {
// CSS classes: added/removed per current state of component properties
this.currentClasses = {
'saveable': this.canSave,
'modified': !this.isUnchanged,
'special': this.isSpecial
};
}
複製代碼
NgStyle
設置多個內聯樣式。NgStyle
須要綁定到一個 key:value
控制對象。 src/app/app.component.html
<div [ngStyle]="currentStyles">
This div is initially italic, normal weight, and extra large (24px).
</div>
複製代碼
src/app/app.component.ts
bash
currentStyles: {};
setCurrentStyles() {
// CSS styles: set per current state of component properties
this.currentStyles = {
'font-weight': 'bold',
};
}
複製代碼
hero
前的 let
關鍵字建立了一個名叫 hero
的模板輸入變量。 這個變量的範圍被限制在所重複模板的單一實例上。事實上,你能夠在其它內置結構型指令中使用一樣的變量名。#phone
的意思就是聲明一個名叫 phone
的變量來引用 <input>
元素。 模板引用變量的做用範圍是整個模板。不要在同一個模板中屢次定義同一個變量名,不然它在運行期間的值是沒法肯定的。<input #phone placeholder="phone number">
複製代碼
Input
)屬性或輸出(Output
)屬性。 但Angular
須要@Input()
和@Output()
裝飾器來標記出那些容許被外部組件綁定到的屬性。 聲明輸入與輸出屬性:@Input() hero: Hero;
@Output() deleteRequest = new EventEmitter<Hero>();
複製代碼
另外:@Input get/set
寫法
_oprType: string ='VIEW';
@Input("oprType")
get oprType(){
retrun this._oprType;
}
set oprType(oprType){
this._oprType = oprType;
...//其餘邏輯處理
}
複製代碼
json
管道對調試綁定特別有用:src/app/app.component.html (pipes-json)
<div>{{currentHero | json}}</div>
複製代碼
它生成的輸出是這樣的:
{ "id": 0, "name": "Hercules", "emotion": "happy",
"birthdate": "1970-02-25T08:00:00.000Z",
"url": "http://www.imdb.com/title/tt0065832/",
"rate": 325 }
複製代碼
ngOnChanges()-》ngOnInit()-》ngDoCheck()-》ngAfterContentInit()-》ngAfterContentChecked()-》ngAfterViewInit()-》ngAfterViewChecked()-》ngOnDestroy()
ngOnInit
生命週期鉤子會在 DOM
更新操做執行前觸發
rxjs
知識var subject = new Subject<string>();
subject.next(1);
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
//observerA: 1
複製代碼
純(pure
)管道與非純(impure
)管道
默認狀況下,管道都是純的。 Angular
只有在它檢測到輸入值發生了純變動時纔會執行純管道。
純變動:是指對原始類型值(String、Number、Boolean、Symbol
)的更改,或者對對象引用(Date、Array、Function、Object
)的更改。 Angular
會忽略對象內部的更改。 若是你更改了輸入日期(Date
)中的月份、往一個輸入數組(Array
)中添加新值或者更新了一個輸入對象(Object
)的屬性,Angular
都不會調用純管道。 Angular
會在每一個組件的變動檢測週期中執行非純管道。 非純管道可能會被調用不少次,和每一個按鍵或每次鼠標移動同樣頻繁。
ElementRef
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
複製代碼
import
語句還從 Angular
的 core
庫中導入了一個 ElementRef
符號。
你能夠在指令的構造函數中注入 ElementRef
,來引用宿主 DOM
元素。 ElementRef
(對視圖中某個宿主元素的引用)經過其 nativeElement
屬性給了你直接訪問宿主 DOM
元素的能力。
DOM
會致使你的應用在 XSS
攻擊前面更加脆弱。當須要直接訪問 當須要直接訪問 DOM
時,請把本 API
做爲最後選擇。
優先使用 Angular
提供的模板和數據綁定機制。 或者你還能夠看看 Renderer2
(實現自定義渲染器),它提供了可安全使用的 API
—— 即便環境沒有提供直接訪問原生元素的功能。
import { Directive, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef, private renderer: Renderer2) {
//el.nativeElement.style.backgroundColor = 'yellow';
this.renderer.setStyle(this.el.nativeElement, "backgroundColor", 'yellow');
}
}
複製代碼
HostListener
把一個事件綁定到一個宿主監聽器,並提供配置元數據。@HostListener('mousedown') onMouseEnter() {
this.highlight(this.highlightColor || this.defaultColor || 'red');
}
複製代碼
mousedown
要監聽的事件。 當mousedown
事件發生時,Angular
就會執行所提供的處理器方法onMouseEnter
。
@Input
。 @Input
裝飾器。 ([ ])
中時,該屬性屬於其它組件或指令,它必須帶有 @Input
裝飾器。<p [appHighlight]="color">Highlight me!</p>
複製代碼
color
屬性位於右側的綁定表達式中,它屬於模板所在的組件。 該模板和組件相互信任。所以 color
不須要 @Input
裝飾器。 appHighlight
屬性位於左側,它引用了 HighlightDirective
中一個帶別名的屬性,它不是模板所屬組件的一部分,所以存在信任問題。 因此,該屬性必須帶 @Input
裝飾器。
bootstrap
—— 根組件,Angular
建立它並插入 index.html
宿主頁面。(*)
寫法是個語法糖,Angular
會把它解開成一個 <ng-template>
標記,包裹着宿主元素及其子元素。 Angular
會在真正渲染的時候填充 <ng-template>
的內容,而且把 <ng-template>
替換爲一個供診斷用的註釋。<ng-template let-hero="hero">
<div *ngIf="hero" [class.odd]="odd">({{i}}) {{hero.name}}</div>
</ng-template>
複製代碼
<ng-template>
中,那些元素就是不可見的(被註釋掉了)。*ngFor
和 *ngIf
不能放在同一個宿主元素上。 *ngFor
放在一個"容器"元素上,再包裝進 *ngIf
元素。 這個元素可使用ng-container
,以避免引入一個新的 HTML
層級。<ul>
<ng-container *ngFor="let menu of menus">
<li *ngIf="!menu.children?.length">
</li>
</ng-container>
</ul>
複製代碼
Angular
的 <ng-container>
是一個分組元素,但它不會污染樣式或元素佈局,由於 Angular
壓根不會把它放進 DOM
中。
template: <ng-template #toolbarTemplate [ngTemplateOutletContext]="{ $implicit: this}"></ng-template>
class: @ViewChild("toolbarTemplate") toolbarTemplate: TemplateRef<any>
簡化寫法:
<ng-template [ngTemplateOutlet]="toolbarTemplate || defaultToolbarTemplate"
[ngTemplateOutletContext]="{ $implicit: this}"></ng-template>
複製代碼
該指令用於基於已有的 TemplateRef 對象,插入對應的內嵌視圖。在應用 NgTemplateOutlet 指令時,咱們能夠經過 [ngTemplateOutletContext] 屬性來設置 EmbeddedViewRef 的上下文對象。綁定的上下文應該是一個對象,此外可經過 let語法來聲明綁定上下文對象屬性名。
angular6.x中ngTemplateOutlet指令的使用示例
表達式中的上下文變量是由"模板引用變量#aa
"、"模板輸入變量let bb
"和"組件的成員cc
"疊加而成的。
優先級:模板輸入變量>模板引用變量>指令的上下文變量>組件類的實例
模板表達式不能引用全局命名空間中的任何東西,好比window
和document
。它們也不能調用console.log
或Math.max
。它們只能引用表達式上下文中的內容。
聲明式組件和入口組件:
聲明式組件會在模板中經過組件聲明的selector
(好比<cmb></cmb>
)加載組件。
入口組件entryComponents
主要有3類:
@NgModule
中的bootstrap
聲明的根組件exports
a
的ngModule
中exports
出一組組件、指令和管道 b
導入了模塊a
b
下的全部組件的模板,均可以使用模塊a
的ngModule
中exports
出的組件、指令和管道<div class="seconds">{{timer.seconds}}</div>
<app-countdown-timer #timer></app-countdown-timer>
複製代碼
這個本地變量方法#timer
是個簡單便利的方法。可是它也有侷限性,由於父組件-子組件的鏈接必須所有在父組件的html
模板中進行。父組件自己的ts
代碼對子組件沒有訪問權。
當父組件類ts
須要這種訪問時,能夠把子組件做爲 ViewChild
,注入到父組件裏面。@ViewChild('timer') timer;
ng-content
父組件頁面parent.html
<attchment-upload>abcde</attchment-upload>
複製代碼
被父組件包含的子組件標籤頁面attchment-upload.html
<div>-- begins --</div>
<ng-content></ng-content>
<div>-- ends --</div>`
複製代碼
輸出:
-- begins --
abcde
-- ends --
複製代碼
以上<ng-content>
標籤是父組件頁面中外來內容的佔位符。 它指明在子組件標籤頁面的哪裏插入這些父組件的外來內容abcde
。
注意:不要在組件標籤的內部聽任何內容 —— 除非你想把這些內容投影進這個組件中。
<ng-container *ngTemplateOutlet="greet"></ng-container>
<ng-template #greet><span>Hello</span></ng-template>
複製代碼
或者
<ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
contentTemplate:TemplateRef<any>
this.contentTemplate=...
//TemplateRef就是對應html中的ng-template標籤
複製代碼
ngIf
寫法<ng-container *ngIf="a.length==0; else elseTemplate">
...
</ng=container>
<ng-template #elseTemplate>
...
</ng-template>
複製代碼
30.ngTemplateOutletContext
<ng-template let-rowData let-rowIndex="rowIndex" let-columns="columns">
<tr>
<td *ngFor="let col of columns;">
// 經過 [ngTemplateOutletContext] 屬性來設置 EmbeddedViewRef:commonBodyTemplate的上下文對象
<ng-container *ngTemplateOutlet="commonBodyTemplate;context:{$implicit:col,rowIndex:rowIndex,rowData:rowData,columns:columns}"></ng-container>
</td>
</tr>
</ng-template>
//若 let 語法未綁定任何屬性名(let-col),則上下文對象中 $implicit 屬性,對應的值col將做爲默認值。
<ng-template #commonBodyTemplate let-col let-rowIndex="rowIndex" let-rowData="rowData">
<ng-container *ngIf="col.field=='idx'">
{{rowIndex+1}}
</ng-container>
<ng-container *ngIf="col.field=='attachSize'">
{{(rowData[col.field]||"--")+(rowData["attachSizeUnit"]||"")}}
</ng-container>
<ng-container *ngIf="editable;else elseTemplate">
<ng-container *ngIf="col.field=='fileName'">
<ng-container *ngIf="rowData['attachmentId']">
<a [href]="attachUrls[rowData['attachmentId']]" [download]="rowData[col.field]">{{rowData[col.field]||""}}</a>
</ng-container>
</ng-container>
<ng-container *ngIf="['idx','attachSize','fileName'].indexOf(col.field)==-1">
{{rowData[col.field]||"--"}}
</ng-container>
</ng-container>
<ng-template #elseTemplate>
<ng-container *ngIf="['idx','attachSize'].indexOf(col.field)==-1">
{{rowData[col.field]||"--"}}
</ng-container>
</ng-template>
</ng-template>
複製代碼
在父頁面中嵌入<app-attachment></app-attachment>
報錯:"app-attachment" is not a unknown element.
緣由:app-attachment
子頁面模板對應的ts
組件沒有包括在父頁面所在的module
中。
32.@Input('companyId') companyId: string;
子組件的初始化constructor
取不到companyId
值,ngOnInit()
能夠 因此初始化放在ngOnInit
中。
33.響應式表單
this.formGroup=fb.group({
contractid:["123",[Validators.required]],
});
this.theDetailGroup.get("finProductName").setValue(this.finProductName);
this.formGroup.get("docmentId").valueChanges.subscribe(value=>{
if(this.existList.findIndex(item=>item.docmentId==value)>-1){
this.formGroup.get("docmentId").setErrors({duplicate:true});
}
});
this.formGroup.get("docmentId").value;
複製代碼
34.this.fb.group({})
響應式表單控件綁定,應該在生命週期以前,即constructor
構造函數中初始化。由於若是放在ngOnInit
中綁定,在表單初始化前對錶單進行賦值操做,會報錯。
35.自定義模塊中exports
使用
將附件聲明到公用模塊
import { NgModule } from '@angular/core';
import { CommonModule} from '@angular/common';
import { AttachmentComponent } from './attachment.component';
@NgModule({
imports: [
CommonModule,
],
exports:[
CommonModule,
AttachmentComponent
],
providers:[],
declarations: [
AttachmentComponent
],
entryComponents:[
AttachmentComponent
]
})
export class SharedModule { }
複製代碼
宿主組件所在的module
中引入公共模塊
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from 'src/app/shared';
@NgModule({
declarations: [
],
imports: [
CommonModule,
SharedModule
],
entryComponents:[]
})
export class MineModule { }
複製代碼
36.自定義雙向數據綁定
<app-base [(companyId)]="companyId"></app-base>
複製代碼
app-base.ts
_companyId = '';
@Output() companyIdChange = new EventEmitter();
@Input('companyId')
get companyId() {
return this._companyId;
}
set companyId(companyId) {
this._companyId = companyId;
this.companyIdChange.emit(companyId);
}
複製代碼
注意:屬性名 + Change
是雙向綁定中Output
的固定寫法
37.在使用一些第三方的組件的時候,要修改組件的樣式。 這種狀況下使用:
:host ::ng-deep .className{
新的樣式......
}
複製代碼
38.要在html
直接使用某個變量。ts
中能夠不要定義這個變量,直接get
。
html:
<div *ngIf="isStatusOkey"></div>
ts:
get isStatusOkey() {
return this.baseInfoConfig.baseInfoData['lpIndentifyStatus'] !== 'OKAY';
}
html:
<mat-grid-tile *ngFor="let item of attachmentTypeList"></mat-grid-tile> ts: get attachmentTypeList() { return this.attachService.getAttachmentTypeList(); } 複製代碼