Angular 属性绑定
属性绑定
Angular 中的属性绑定可帮助你设置 HTML 元素或指令的属性值。使用属性绑定,可以执行诸如切换按钮、以编程方式设置路径,以及在组件之间共享值之类的功能。
先决条件
为了充分理解属性绑定,你应该熟悉以下内容:
- 组件基础
- 模板基础
- 绑定语法
了解数据流
属性绑定在单一方向上将值从组件的属性送到目标元素的属性。
绑定到属性
要绑定到元素的属性,请将其括在方括号 []
内,该括号会将属性标为目标属性。目标属性就是你要对其进行赋值的 DOM 属性。例如,以下代码中的目标属性是 img 元素的 src
属性。
<img [src]="itemImageUrl">
在大多数情况下,目标的名称就是 Property 的名称,哪怕它看起来像 Attribute 的名称。在这个例子中,src
就是 <img>
元素的 Property 名称。
方括号 []
使 Angular 将等号的右侧看作动态表达式进行求值。如果不使用方括号,Angular 就会将右侧视为字符串字面量并将此属性设置为该静态值。
<app-item-detail childItem="parentItem"></app-item-detail>
省略方括号就会渲染出字符串 parentItem
,而不是 parentItem
的值。
将元素的属性设置为组件属性的值
要将 <img>
的 src
属性绑定到组件的属性,请将目标 src
放在方括号中,后跟等号,然后是组件的属性。在这里组件的属性是 itemImageUrl
。
<img [src]="itemImageUrl">
在组件类 AppComponent
中声明 itemImageUrl
属性。
itemImageUrl = '../assets/phone.png';
colspan 和 colSpan
最容易混淆的地方是 colspan
这个 Attribute 和 colSpan
这个 Property。请注意,这两个名称只有一个字母的大小写不同。
如果你这样写:
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
你会收到此错误:
Template parse errors:
Can't bind to 'colspan' because it isn't a known built-in property
如消息中所示,<td>
元素没有 colspan
Property。这是正确的,因为 colspan
是一个 Attribute — colSpan
(带大写 S
)才是相应的 Property。插值和 Property 绑定只能设置 Property,不能设置 Attribute。
相反,你应该使用 Property 绑定并将其编写为:
<!-- Notice the colSpan property is camel case -->
<tr><td [colSpan]="1 + 1">Three-Four</td></tr>
另一个示例是在组件说它自己 isUnchanged
时禁用按钮:
<!-- Bind button disabled state to `isUnchanged` property -->
<button [disabled]="isUnchanged">Disabled Button</button>
另一个是设置指令的属性:
<p [ngClass]="classes">[ngClass] binding to the classes property making this blue</p>
还有一个是设置自定义组件的模型属性,这是父组件和子组件进行通信的一种好办法:
<app-item-detail [childItem]="parentItem"></app-item-detail>
切换按钮功能
若要根据布尔值禁用按钮的功能,请将 DOM 的 disabled
Property 设置为类中的源属性(可能为 true
或 false
)。
<!-- Bind button disabled state to `isUnchanged` property -->
<button [disabled]="isUnchanged">Disabled Button</button>
由于 AppComponent
中属性 isUnchanged
的值是 true
,Angular 会禁用该按钮。
isUnchanged = true;
设置指令的属性
要设置指令的属性,请将指令放在方括号中,例如 [ngClass]
,后跟等号和一个源属性。在这里,这个源属性的值是 classes
。
<p [ngClass]="classes">[ngClass] binding to the classes property making this blue</p>
要使用该属性,必须在组件类中声明它,在这里是 AppComponent
。其 classes
的值是 special
。
classes = 'special';
Angular 会将 special
类应用到 <p>
元素,以便你可以通过 special
来应用 CSS 样式。
在组件之间绑定值
要设置自定义组件的模型属性,请将目标属性(此处为 childItem
)放在方括号 []
中,其后跟着等号与源属性。在这里,这个源属性是 parentItem
。
<app-item-detail [childItem]="parentItem"></app-item-detail>
要使用目标和源属性,必须在它们各自的类中声明它们。
在组件类(这里是 ItemDetailComponent
)中声明 childItem
的目标。
例如,以下代码在其组件类(这里是 ItemDetailComponent
)中声明了 childItem
的目标。
然后,代码包含一个带有 @Input()
装饰器的 childItem
属性,这样才能让数据流入其中。
@Input() childItem = '';
接下来,代码在其组件类(这里是 AppComponent
)中声明属性 parentItem
。在这个例子中, childItem
的类型为 string
,因此 parentItem
也必须为字符串。在这里,parentItem
的字符串值为 lamp
。
parentItem = 'lamp';
这种配置方式下,<app-item-detail>
的视图使用来自 childItem
的值 lamp
。
属性绑定与安全性
属性绑定可以帮助确保内容的安全。例如,考虑以下恶意内容。
evilTitle = 'Template <script>alert("evil never sleeps")</script> Syntax';
组件模板对内容进行插值,如下所示:
<p><span>"{{evilTitle}}" is the <i>interpolated</i> evil title.</span></p>
浏览器不会处理 HTML,而是原样显示它,如下所示。
"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title.
Angular 不允许带有 <script>
标记的 HTML,既不能用于插值也不能用于属性绑定,这样就会阻止运行 JavaScript。
但是,在以下示例中,Angular 在显示值之前会先对它们进行无害化处理。
<!--
Angular generates a warning for the following line as it sanitizes them
WARNING: sanitizing HTML stripped some content (see https://g.co/ng/security#xss).
-->
<p>"<span [innerHTML]="evilTitle"></span>" is the <i>property bound</i> evil title.</p>
插值处理 <script>
标记的方式与属性绑定的方式不同,但这两种方法都可以使内容无害。以下是经过无害化处理的 evilTitle
示例的浏览器输出。
"Template Syntax" is the property bound evil title.
属性绑定和插值
通常,插值和属性绑定可以达到相同的结果。以下绑定会做相同的事。
<p><img src="{{itemImageUrl}}"> is the <i>interpolated</i> image.</p>
<p><img [src]="itemImageUrl"> is the <i>property bound</i> image.</p>
<p><span>"{{interpolationTitle}}" is the <i>interpolated</i> title.</span></p>
<p>"<span [innerHTML]="propertyTitle"></span>" is the <i>property bound</i> title.</p>
将数据值渲染为字符串时,可以使用任一种形式,只是插值形式更易读。但是,要将元素属性设置为非字符串数据值时,必须使用属性绑定。