
@Component裝飾器1.1 @Component裝飾器的用途
聲明一個組件時,在組件類的之上要用@Component裝飾器來告知Angular這是一個組件。 【相關教學推薦:《angular教學》】
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-product-alerts',
templateUrl: './product-alerts.component.html',
styleUrls: ['./product-alerts.component.css']
})
export class ProductAlertsComponent implements OnInit {
constructor() { }
ngOnInit() {
}
} 1.2 @Component裝飾器的常用選項
@Component裝飾器繼承於Directive ,這個css選擇器用於在模板中標記出該指令,並觸發該指令的實例化。
1.2.1继承自@Directive装饰器的选项
| 選項 | 類型 | 說明 |
|---|---|---|
| selector | string | css選擇器名,用於在模板中標記出該指令(組件),並觸發其實例化 |
| inputs | string[] | Angular 會在變更檢測期間自動更新輸入屬性。 inputs 屬性定義了一組從directiveProperty 到bindingProperty 的配置項: · directiveProperty 用來指定要寫入值的指令內屬性。 · bindingProperty 用來指定要從中讀取值的DOM 屬性。當沒有提供bindingProperty 時,就假設它和directiveProperty 一樣。 |
| outputs | string[] | 一組可供事件綁定的輸出屬性。當輸出屬性發出事件時,就會呼叫範本中一個附加到該事件的處理器。每個輸出屬性都會把directiveProperty 對應到bindingProperty: · directiveProperty 指定要發出事件的元件屬性。 · bindingProperty 指定要附加事件處理器的HTML 屬性。 |
| provides | Provider[] | 服務提供者的集合 |
| exportAs | string | 一個或多個名字,可以用來在範本中把該指令賦值給一個變數。當有多個名字時,請使用逗號分隔它們。 |
| queries | {[key:string]:any} | 配置將要注入到該指令中的一些查詢。內容查詢會在呼叫ngAfterContentInit 回調之前設定好。 試著查詢會在呼叫ngAfterViewInit 回呼之前設定好。 |
| jit | true | 如果為true,則指令/元件將會被AOT 編譯器忽略,因此永遠只會由JIT 編譯。這個選項是為了支援未來的Ivy 編譯器,目前還沒有效果。 |
| host | {[key:string]:string} | 使用一組鍵-值對,把類別的屬性對應到宿主元素的綁定(Property、Attribute 和事件)。 Angular 在變更偵測期間會自動檢查宿主Property 綁定。 如果綁定的值發生了變化,Angular 就會更新該指令的宿主元素。當key 是宿主元素的Property 時,這個Property 值就會傳播到指定的DOM 屬性。當key 是DOM 中的靜態Attribute 時,這個Attribute 值就會傳播到宿主元素上指定的Property 去。對於事件處理: · 它的key 就是該指令想要監聽的DOM 事件。 若要監聽全域事件,請把要監聽的目標加到事件名稱的前面。 這個目標可以是window、document 或body。 · 它的value 就是當該事件發生時要執行的語句。如果該語句回傳false,那麼就會呼叫這個DOM 事件的preventDefault 函數。 這個語句中可以引用局部變數$event 來取得事件資料。 |
1.2.2 @Component自己特有的选项
| 選項 | 類型 | 說明 |
|---|---|---|
| changeDetection | ChangeDetectionStrategy | 當元件實例化之後,Angular 就會建立一個變更偵測器,它負責傳播元件各個綁定值的變化。 此策略是下列值之一: · ChangeDetectionStrategy#OnPush(0) 把策略設定為CheckOnce(按需)。 · ChangeDetectionStrategy#Default(1) 把策略設定為CheckAlways。 |
| viewProviders | Provider[] | 定義一組可注入對象,它們在視圖的各個子節點中可用 |
| moduleId | string | 包含該組件的那個模組的ID。該元件必須能解析模板和樣式表中使用的相對URL。 SystemJS 在每個模組中都導出了__moduleName 變數。在CommonJS 中,它可以設定為module.id。 |
| templateUrl | string | 組件模板檔的URL。如果提供了它,就不要再用template 來提供內聯模板了。 |
| template | string | 組件的內嵌模板。如果提供了它,就不要再用templateUrl 提供模板了。 |
| styleUrls | string[] | 一個或多個URL,指向包含本元件CSS 樣式表的檔案。 |
| styles | string[] | 本組件所使用的一個或多個內嵌CSS 樣式。 |
| animations | any[] | 一個或多個動畫trigger() 調用,包含一些state() 和transition() 定義。 |
| encapsulation | ViewEncapsulation | 供模板和CSS 樣式使用的樣式封裝策略。取值為: · ViewEncapsulation.ShadowDom:使用Shadow DOM。它只在原生支援Shadow DOM 的平台上才能運作。 · ViewEncapsulation.Emulated:使用墊片(shimmed) CSS 來模擬原生行為。 · ViewEncapsulation.None:使用全域CSS,不做任何封裝。 如果沒有提供,該值就會從CompilerOptions 中取得它。預設的編譯器選項是ViewEncapsulation.Emulated。如果該策略設定為ViewEncapsulation.Emulated,且該元件沒有指定styles 或styleUrls,就會自動切換到ViewEncapsulation.None。 |
| interpolation | [string, string] | 改寫預設的插值表達式起止分界符({ { 和}}) |
| entryComponents | Array<Type | any[]> |
| preserveWhitespaces | boolean | 為true 則保留,為false 則從編譯後的模板中移除可能多餘的空白字元。 空白字元就是指那些能在JavaScript 正規表示式中符合s 的字元。預設為false,除非透過編譯器選項改寫了它。 |
selector選擇器可使用下列形式之一:
element-name : 根據元素名稱選取[attribute] : 依屬性名稱選取.class : 依類別名稱選取[attribute=value] : 依屬性名稱與屬性值選取not(sub_selector) : 只有當元素不符子選擇器sub_selector 的時候才選取selector1, selector2 :不論該元素不符時都選取2.1 element-name : 依元素名稱選取
@Component({
selector: 'app-element',
template: './element.component.html',
styleUrls: ['./element.component.css']
}) <app-element></app-element>
2.2 [attribute] : 依屬性名稱選取
@Component({
selector: '[app-element]',
template: './element.component.html',
styleUrls: ['./element.component.css']
}) <div app-element></div>
2.3 .class : 依類別名稱選取
@Component({
selector: '.app-element',
template: './element.component.html',
styleUrls: ['./element.component.css']
}) <div class="app-element"></div>
host : {[key:string]:string}使用一組鍵-值對,把類別的屬性對應到宿主元素的綁定(Property 、Attribute 和事件)。
Angular 在變更偵測期間會自動檢查宿主Property 綁定。 如果綁定的值發生了變化,Angular 就會更新該指令的宿主元素。
對於事件處理:
3.1 attribute和property
異同:
所以在angular2 中双向綁定實作是由dom 的property實現的,所以指令綁定的是property ,但是在某些情況下dom 不存在某個property 例如colspan,rowspan 等,這時想要綁定html 標籤特性需要用到attr :
<table width="100%" border="10px solid">
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
<tr>
<td [attr.colspan]=colnum>January</td>
</tr>
<tr>
<td [attr.colspan]=colnum>February</td>
</tr>
</table>
let colnum:number = 2; 3.2 使用host綁定class
@Component({
selector: '.app-element',
template: './element.component.html',
styleUrls: ['./element.component.css'],
host: {
'[class.default-class]': 'useDefault'
},
encapsulation: ViewEncapsulation.None // 讓宿主元素也用上element.component.css 樣式。否則,預設膠囊封裝避免CSS污染。
})
export class AppElementComponent {
@Input() useDefault = true;
} <div class="app-element"></div>
3.3 使用host綁定style
@Component({
selector: '.app-element',
template: './element.component.html',
styleUrls: ['./element.component.css'],
host: {
'[style.background]': 'inputBackground'
}
})
export class AppElementComponent {
@Input() inputBackground = 'red';
} <div class="app-element"></div>
3.4 使用host綁定事件
@Component({
selector: '.app-element',
template: './element.component.html',
styleUrls: ['./element.component.css'],
host: {
'(click)': 'onClick($event)'
}
})
export class AppElementComponent {
public onClick($event) {
console.log($event);
}
} <div class="app-element"></div>
encapsulation (封裝)供模板和CSS 樣式使用的樣式封裝策略。
4.1 Web Components
透過標準化的非侵入的方式封裝一個元件,每個元件能組織好它自己的HTML 結構、CSS 樣式、JavaScript 程式碼,並且不会干扰頁面上的其他元素。
Web Components 由以下四種技術組成:
4.2 Shadow DOM
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Shadow DOM</title>
<style type="text/css">
.shadowroot_son {
color: #f00;
}
</style>
</head>
<body>
<p>我不在Shadow Host內</p>
<div>Hello, world!</div>
<script>
// 影子宿主(shadow host)
var shadowHost = document.querySelector('.shadowhost');
// 建立影子根(shadow root)
var shadowRoot = shadowHost.createShadowRoot();
// 影子根作為影子樹的第一個節點,其他的節點例如p節點都是它的子節點。
shadowRoot.innerHTML = '<p>我在Shadow Host內</p>';
</script>
</body>
<html> 4.3 ViewEncapsulation
ViewEncapsulation 允許設定三個可選的值:
4.3.1 ViewEncapsulation.None
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h4>Welcome to Angular World</h4>
<p class="greet">Hello {{name}}</p>
`,
styles: [`
.greet {
background: #369;
color: white;
}
`],
encapsulation: ViewEncapsulation.None // None | Emulated | ShadowDom
})
export class AppComponent {
name: string = 'Semlinker';
} ViewEncapsulation.None設定的結果是沒有Shadow DOM ,並且所有的樣式都應用到整个document ,換句話說,組件的樣式會受外界影响,可能被覆盖掉。
4.3.2 ViewEncapsulation.Emulated
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'my-app',
...,
encapsulation: ViewEncapsulation.Emulated // None | Emulated | ShadowDom
})
export class AppComponent {
name: string = 'Semlinker';
} ViewEncapsulation.Emulated設定的結果是沒有Shadow DOM ,但透過Angular提供的样式包装机制來封裝元件,使得元件的樣式不受外部影响。雖然樣式仍然是應用到整个document ,但Angular 為.greet類別創建了一個[_ngcontent-cmy-0]選擇器。可以看出,我們为组件定义的样式,被Angular 修改了。其中的_nghost-cmy- 和_ngcontent-cmy-用來实现局部的样式。
4.3.3 ViewEncapsulation.ShadowDom
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'my-app',
...,
encapsulation: ViewEncapsulation.ShadowDom // None | Emulated | ShadowDom
})
export class AppComponent {
name: string = 'Semlinker';
} ViewEncapsulation.ShadowDom設定的結果是使用原生的Shadow DOM特性。 Angular 會把元件依照瀏覽器支援的Shadow DOM 形式渲染。