Attribute 綁定、類綁定和樣式綁定
Angular 中的 Attribute 綁定可幫助你直接設(shè)置 Attribute 值。使用 Attribute 綁定,你可以提升無障礙性、動(dòng)態(tài)設(shè)置應(yīng)用程序樣式以及同時(shí)管理多個(gè) CSS 類或樣式。
包含本指南中的代碼片段的可工作示例,請參閱現(xiàn)場演練 / 下載范例。
綁定到 Attribute
建議你盡可能設(shè)置帶有 Property 綁定的元素的 Property。但是,有時(shí)你沒有可綁定的元素 Property。在這種情況下,可以使用 Attribute 綁定。
例如,ARIA和SVG 只有 Attribute。 ARIA 和 SVG 都不對應(yīng)于元素的 Property,也不設(shè)置元素的 Property。在這些情況下,必須使用 Attribute 綁定,因?yàn)闆]有相應(yīng)的目標(biāo) Property。
語法
Attribute 綁定語法類似于 Property 綁定,但不是直接在方括號之間放置元素的 Property,而是在 Attribute 名稱前面加上前綴 ?attr
?,后跟一個(gè)點(diǎn) ?.
?。然后,使用解析為字符串的表達(dá)式設(shè)置 Attribute 值。
<p [attr.attribute-you-are-targeting]="expression"></p>
當(dāng)表達(dá)式解析為 ?null
?或 ?undefined
?時(shí),Angular 會完全刪除該 Attribute。
綁定 ARIA Attribute
Attribute 綁定的主要用例之一是設(shè)置 ARIA Attribute,如下所示:
<button [attr.aria-label]="actionName">{{actionName}} with Aria</button>
綁定到 colspan
Attribute 綁定的另一個(gè)常見用例是綁定到表格中的 ?colspan
?Attribute。?colspan
?Attribute 可幫助你以編程方式讓表格保持動(dòng)態(tài)。根據(jù)應(yīng)用中用來填充表的數(shù)據(jù)量,某一行要跨越的列數(shù)可能會發(fā)生變化。
要將 Attribute 綁定到 ?<td>
? 的 ?colspan
?Attribute:
- 使用以下語法指定 ?
colspan
?:?[attr.colspan]
? 。
- 將 ?
[attr.colspan]
? 設(shè)置為等于某個(gè)表達(dá)式。
在下面的示例中,我們將 ?colspan
?Attribute 綁定到表達(dá)式 1 + 1。
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
此綁定會導(dǎo)致 ?<tr>
? 跨越兩列。
有時(shí),Property 名和 Attribute 名之間存在差異。
?colspan
?是 ?<tr>
? 的 Attribute,而 ?colSpan
?(注意 “S” 是大寫)是 Property。使用 Attribute 綁定時(shí),請使用帶小寫 “s” 的 ?colspan
?。
綁定到 class Attribute
可以用類綁定從元素的 ?class
?Attribute 中添加和刪除 CSS 類名稱。
綁定到單個(gè) CSS class
要?jiǎng)?chuàng)建單個(gè)類綁定,請使用前綴 ?class
?后跟一個(gè)點(diǎn)和 CSS 類的名稱,例如 ?[class.sale]="onSale"
?。?onSale
?為真值時(shí)添加類,在表達(dá)式為假值時(shí)(?undefined
?除外)刪除類。
綁定到多個(gè) CSS 類
要綁定到多個(gè)類,請使用 ?[class]
? 來設(shè)置表達(dá)式 - 例如,?[class]="classExpression"
?,此表達(dá)式可以取如下值:
- 用空格分隔的類名字符串
- 以類名作為鍵名并將真或假表達(dá)式作為值的對象。
- 類名的數(shù)組。
對于對象格式,Angular 會在其關(guān)聯(lián)的值為真時(shí)才添加類。
對于任何類似對象的表達(dá)式(例如 ?object
?、?Array
?、?Map
?或 ?Set
?,必須更改對象的引用,Angular 才能更新類列表。在不更改對象引用的情況下只更新其 Attribute 是不會生效的。
如果同一類名有多個(gè)綁定,Angular 會根據(jù)樣式優(yōu)先級來確定要使用的綁定。
下表是各種類綁定語法的小結(jié)。
綁定類型
|
語法
|
輸入類型
|
范例輸入值
|
單一類綁定
|
[class.sale]="onSale"
|
boolean | undefined | null
|
true , false
|
多重類綁定
|
[class]="classExpression"
|
string
|
"my-class-1 my-class-2 my-class-3"
|
Record<string, boolean | undefined | null>
|
{foo: true, bar: false}
|
Array <string > |
['foo', 'bar']
|
綁定到 style Attribute
可以用樣式綁定來動(dòng)態(tài)設(shè)置樣式。
綁定到單一樣式
要?jiǎng)?chuàng)建對單個(gè)樣式的綁定,請使用前綴 ?style
?后跟一個(gè)點(diǎn)和 CSS style Attribute 的名稱,例如 ?[style.width]="width"
?。 Angular 會將該 Attribute 設(shè)置為綁定表達(dá)式的值,這個(gè)值通常是一個(gè)字符串。(可選)你還可以添加單位擴(kuò)展,例如 ?em
?或 ?%
? ,它的值需要數(shù)字類型。
你可以用中線格式或 camelCase 格式編寫樣式 Attribute 名。
<nav [style.background-color]="expression"></nav>
<nav [style.backgroundColor]="expression"></nav>
綁定到多個(gè)樣式
要切換多個(gè)樣式,請綁定到 ?[style]
? Attribute,例如 ?[style]="styleExpression"
? 。?styleExpression
?可以是如下格式之一:
- 樣式的字符串列表,例如 ?
"width: 100px; height: 100px; background-color: cornflowerblue;"
?。
- 一個(gè)對象,其鍵名是樣式名,其值是樣式值,比如 ?
{width: '100px', height: '100px', backgroundColor: 'cornflowerblue'}
?。
注意,不支持把數(shù)組綁定給 ?[style]
?。
當(dāng)把 ?[style]
? 綁定到對象表達(dá)式時(shí),該對象的引用必須改變,這樣 Angular 才能更新這個(gè)類列表。在不改變對象引用的情況下更新其屬性值是不會生效的。
單樣式和多樣式綁定示例
@Component({
selector: 'app-nav-bar',
template: `
<nav [style]='navStyle'>
<a [style.text-decoration]="activeLinkStyle">Home Page</a>
<a [style.text-decoration]="linkStyle">Login</a>
</nav>`
})
export class NavBarComponent {
navStyle = 'font-size: 1.2rem; color: cornflowerblue;';
linkStyle = 'underline';
activeLinkStyle = 'overline';
}
如果同一個(gè)樣式 Attribute 有多個(gè)綁定,Angular 將使用樣式優(yōu)先級來確定要使用的綁定。
下表是各種樣式綁定語法的小結(jié)。
綁定類型
|
語法
|
輸入屬性
|
范例輸入值
|
單一樣式綁定
|
[style.width]="width"
|
string | undefined | null
|
"100px"
|
帶單位的單一樣式綁定
|
[style.width.px]="width"
|
number | undefined | null
|
100
|
多重樣式綁定
|
[style]="styleExpression"
|
string
|
"width: 100px; height: 100px"
|
Record<string, string | undefined | null>
|
{width: '100px', height: '100px'}
|
?NgStyle
?指令可以用作代替直接綁定 ?[style]
? 的方法。但是,最好使用上述不用 ?NgStyle
?的綁定語法,因?yàn)橛捎?nbsp;Angular 中樣式綁定的改進(jìn),?NgStyle
?不再提供顯著價(jià)值,將來可能會被刪除。
樣式優(yōu)先級
一個(gè) HTML 元素可以將其 CSS 類列表和樣式值綁定到多個(gè)源(例如,來自多個(gè)指令的宿主綁定)。
當(dāng)有多個(gè)到相同的類名或樣式屬性的綁定時(shí),Angular 使用一組優(yōu)先規(guī)則來解決沖突并確定最終將哪些類或樣式應(yīng)用于元素。
樣式優(yōu)先級(從高到低)
- 模板綁定
- 屬性綁定(例如,?
<div [class.foo]="hasFoo">
? 或 ?<div [style.color]="color">
? )
- 映射表綁定(例如,?
<div [class]="classExpr">
? 或 ?<div [style]="styleExpr">
? )
- 靜態(tài)值(例如 ?
<div class="foo">
? 或 ?<div style="color: blue">
? )
- 指令宿主綁定
- 屬性綁定(例如,?
host: {'[class.foo]': 'hasFoo'}
? 或 ?host: {'[style.color]': 'color'}
? )
- 映射表綁定(例如,?
host: {'[class]': 'classExpr'}
? 或 ?host: {'[style]': 'styleExpr'}
? )
- 靜態(tài)值(例如,?
host: {'class': 'foo'}
? 或 ?host: {'style': 'color: blue'}
? )
- 組件宿主綁定
- 屬性綁定(例如,?
host: {'[class.foo]': 'hasFoo'}
? 或 ?host: {'[style.color]': 'color'}
? )
- 映射表綁定(例如,?
host: {'[class]': 'classExpr'}
? 或 ?host: {'[style]': 'styleExpr'}
? )
- 靜態(tài)值(例如,?
host: {'class': 'foo'}
? 或 ?host: {'style': 'color: blue'}
? )
總之,類或樣式綁定越具體,其優(yōu)先級就越高。
綁定到具體類(例如 ?[class.foo]
? )將優(yōu)先于不特定 ?[class]
? 的綁定,并且綁定到特定樣式(例如 ?[style.bar]
? )將優(yōu)先于不特定 ?[style]
? 的綁定。
<h3>Basic specificity</h3>
<div [class.special]="isSpecial" [class]="classExpression">Some text.</div>
<div [style.border]="border" [style]="styleExpression">Some text.</div>
當(dāng)涉及不同來源的綁定時(shí),也適用這些特異性規(guī)則。元素可能具有在其聲明的模板中的綁定、在其匹配的指令中的宿主綁定、在其匹配的組件中的宿主綁定。
模板綁定是最具體的,因?yàn)樗鼈儠苯忧遗潘貞?yīng)用于元素,因此它們具有最高的優(yōu)先級。
指令宿主綁定被認(rèn)為不太具體,因?yàn)橹噶羁梢栽诙鄠€(gè)位置使用,因此它們的優(yōu)先級低于模板綁定。
指令通常會增強(qiáng)組件的行為,因此組件的宿主綁定具有最低的優(yōu)先級。
<h3>Source specificity</h3>
<comp-with-host-binding [class.special]="isSpecial" dirWithClassBinding></comp-with-host-binding>
<div>
<comp-with-host-binding [style.color]="color" dirWithStyleBinding></comp-with-host-binding>
</div>
<h3>Dynamic vs static</h3>
<div class="special" [class]="classExpression">Some text.</div>
<div style="border: dotted darkblue 3px" [style]="styleExpression">Some text.</div>
<div class="readability">
<comp-with-host-binding dirWithHostBinding></comp-with-host-binding>
</div>
<app-my-input-with-attribute-decorator type="number"></app-my-input-with-attribute-decorator>
此外,綁定會優(yōu)先于靜態(tài)屬性。
在這里,?class
?和 ?[class]
? 具有相似的特異性,但是 ?[class]
? 綁定更優(yōu)先一些,因?yàn)樗莿?dòng)態(tài)的。
<h3>Dynamic vs static</h3>
<div class="special" [class]="classExpression">Some text.</div>
<div style="border: dotted darkblue 3px" [style]="styleExpression">Some text.</div>
委托給優(yōu)先級較低的樣式
可以用 ?undefined
?值來把高優(yōu)先級的樣式“委托”給較低優(yōu)先級的樣式。將樣式屬性設(shè)置為 ?null
?可以確保樣式被刪除,而將其設(shè)置為 ?undefined
?將導(dǎo)致 Angular 回退到該樣式的次高優(yōu)先級綁定。
例如,考慮以下模板:
<comp-with-host-binding dirWithHostBinding></comp-with-host-binding>
假設(shè) ?dirWithHostBinding
?指令和 ?comp-with-host-binding
? 組件都具有 ?[style.width]
? 宿主綁定。在這里,如果 ?dirWithHostBinding
?將其綁定設(shè)置為 ?undefined
?,則 ?width
?屬性將回退到 ?comp-with-host-binding
? 宿主綁定的值。但是,如果 ?dirWithHostBinding
?將其綁定設(shè)置為 ?null
?,則會完全刪除 ?width
?
注入屬性值
在某些情況下,你需要根據(jù)在 host 元素上以 HTML 屬性的形式設(shè)置的靜態(tài)值來區(qū)分組件或指令的行為。例如,你可能有一個(gè)指令,需要知道 ?<button>
? 或 ?<input>
? 元素的 ?type
?值。
Attribute參數(shù)裝飾器非常適合通過依賴注入來將 HTML 屬性的值傳遞給組件/指令構(gòu)造函數(shù)。
這里注入的值將捕獲指定 HTML 屬性的當(dāng)前值。將來對屬性值的修改不會反映到注入的值中。
import { Attribute, Component } from '@angular/core';
@Component({
selector: 'app-my-input-with-attribute-decorator',
template: '<p>The type of the input is: {{ type }}</p>'
})
export class MyInputWithAttributeDecoratorComponent {
constructor(@Attribute('type') public type: string) { }
}
<app-my-input-with-attribute-decorator type="number"></app-my-input-with-attribute-decorator>
在前面的示例中,?app.component.html
?的結(jié)果為:The type of the input is: number。
另一個(gè)示例是RouterOutlet指令,該指令利用 Attribute 裝飾器檢索每個(gè)路由插座上的唯一名稱。
@ATTRIBUTE() VS @INPUT()
請記住,要持續(xù)跟蹤 Attribute 的值并更新關(guān)聯(lián)的 Property 時(shí),請使用 ?@Input()
?。若要將 HTML 屬性的值注入到組件或指令的構(gòu)造函數(shù)中,請使用?@Attribute()
?。