https://angular.cn/guide/template-syntax
{{}} 和"" 如果嵌套,{{}}里面求完值,""就是原意
<h3>
{{title}}
<img src="{{heroImageUrl}}" style="height:30px">
</h3>
但如果不嵌套,双花括号中的title
和引号中的isUnchanged
所引用的都是AppComponent
中的属性。
{{title}}
<span [hidden]="isUnchanged">changed</span>
模板输入变量 (let hero
)和模板引用变量(#heroInput
)
<div *ngFor="let hero of heroes">{{hero.name}}</div>
<input #heroInput> {{heroInput.value}}
hero.name 的hero指的是let hero
模板语句Template statements
有副作用A template statement has a side effect. That's the whole point of an event. It's how you update application state from user action.
<button (click)="deleteHero()">Delete hero</button>
和表达式中一样,语句只能引用语句上下文中 —— 通常是正在绑定事件的那个组件实例。
语句上下文可以引用模板自身上下文中的属性。 在下面的例子中,就把模板的$event
对象、模板输入变量(let hero
)和模板引用变量 (#heroForm
)传给了组件中的一个事件处理器方法。
<button (click)="onSave($event)">Save</button>
<button *ngFor="let hero of heroes" (click)="deleteHero(hero)">{{hero.name}}</button>
<form #heroForm (ngSubmit)="onSubmit(heroForm)"> ... </form>
在上面的deleteHero(hero)
中,hero
是一个模板输入变量,而不是组件中的hero
属性。
要想理解 Angular 绑定如何工作,重点是搞清 HTML attribute 和 DOM property 之间的区别。
attribute 是由 HTML 定义的。property 是由 DOM (Document Object Model) 定义的。
少量 HTML attribute 和 property 之间有着 1:1 的映射,如
id
。有些 HTML attribute 没有对应的 property,如
colspan
。有些 DOM property 没有对应的 attribute,如
textContent
。大量 HTML attribute看起来映射到了property…… 但却不像我们想的那样!
最后一类尤其让人困惑…… 除非我们能理解这个普遍原则:
attribute 初始化 DOM property,然后它们的任务就完成了。property 的值可以改变;attribute 的值不能改变。
当浏览器渲染<input type="text" value="Bob">
时,它将创建相应 DOM 节点, 其value
property 被初始化为 “Bob”。
当用户在输入框中输入 “Sally” 时,DOM 元素的value
property 变成了 “Sally”。 但是这个 HTML value
attribute 保持不变。如果我们读取 input 元素的 attribute,就会发现确实没变:input.getAttribute('value') // 返回 "Bob"
。
HTML attribute value
指定了初始值;DOM value
property 是当前值。
disabled
attribute 是另一个古怪的例子。按钮的disabled
property 是false
,因为默认情况下按钮是可用的。 当我们添加disabled
attribute 时,只要它出现了按钮的disabled
property 就初始化为true
,于是按钮就被禁用了。
添加或删除disabled
attribute会禁用或启用这个按钮。但 attribute 的值无关紧要,这就是我们为什么没法通过 <button disabled="false">仍被禁用</button>
这种写法来启用按钮。
设置按钮的disabled
property(如,通过 Angular 绑定)可以禁用或启用这个按钮。 这就是 property的价值。
模板绑定是通过 property 和事件来工作的,而不是 attribute。
image 元素的src
属性会被绑定到组件的heroImageUrl
属性上:
<img [src]="heroImageUrl">
setting a property of a directive:
<div [ngClass]="classes">[ngClass] binding to the classes property</div>
设置自定义组件的模型属性(这是父子组件之间通讯的重要途径):
<app-hero-detail [hero]="currentHero"></app-hero-detail>
不能使用属性绑定来从目标元素拉取值,也不能绑定到目标元素的属性来读取它。只能设置它。
如果必须读取目标元素上的属性或调用它的某个方法,得用另一种技术。 参见 API 参考手册中的ViewChild 和 ContentChild。
方括号告诉 Angular 要计算模板表达式。 如果忘了加方括号,Angular 会把这个表达式当做字符串常量看待,并用该字符串来初始化目标属性。 它不会计算这个字符串。
当满足下列条件时,应该省略括号:
目标属性接受字符串值。
字符串是个固定值,可以直接合并到模块中。
这个初始值永不改变。
把HeroDetailComponent
的prefix
属性初始化为固定的字符串,而不是模板表达式。Angular 设置它,然后忘记它。[hero]
绑定是组件的currentHero
属性的活绑定,它会一直随着更新。
<app-hero-detail prefix="You are my" [hero]="currentHero"></app-hero-detail>
属性绑定还是插值表达式?
下列这几对绑定做的事情完全相同:
<p><img src="{{heroImageUrl}}"> is the <i>interpolated</i> image.</p>
<p><img [src]="heroImageUrl"> is the <i>property bound</i> image.</p> <p><span>"{{title}}" is the <i>interpolated</i> title.</span></p>
<p>"<span [innerHTML]="title"></span>" is the <i>property bound</i> title.</p>
可读性,所以倾向于插值表达式。
但数据类型不是字符串时,就必须使用属性绑定了。
当元素没有属性可绑的时候,就必须使用 attribute 绑定。
考虑 ARIA, SVG 和 table 中的 colspan/rowspan 等 attribute。 它们是纯粹的 attribute,没有对应的属性可供绑定。
[attr.colspan]