angular 模板语法,官方文档摘录

https://angular.cn/guide/template-syntax

{{}} 和"" 如果嵌套,{{}}里面求完值,""就是原意

<h3>
  {{title}}
  <img src="{{heroImageUrl}}" >
</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 节点, 其valueproperty 被初始化为 “Bob”。

当用户在输入框中输入 “Sally” 时,DOM 元素的valueproperty 变成了 “Sally”。 但是这个 HTML valueattribute 保持不变。如果我们读取 input 元素的 attribute,就会发现确实没变:input.getAttribute('value') // 返回 "Bob"

HTML attribute value指定了初始;DOM value property 是当前

disabled attribute 是另一个古怪的例子。按钮的disabledpropertyfalse,因为默认情况下按钮是可用的。 当我们添加disabledattribute 时,只要它出现了按钮的disabledproperty 就初始化为true,于是按钮就被禁用了。

添加或删除disabledattribute会禁用或启用这个按钮。但 attribute 的值无关紧要,这就是我们为什么没法通过 <button disabled="false">仍被禁用</button>这种写法来启用按钮。

设置按钮的disabledproperty(如,通过 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 参考手册中的ViewChildContentChild

方括号告诉 Angular 要计算模板表达式。 如果忘了加方括号,Angular 会把这个表达式当做字符串常量看待,并用该字符串来初始化目标属性。 它不会计算这个字符串。

当满足下列条件时,应该省略括号:

  • 目标属性接受字符串值。

  • 字符串是个固定值,可以直接合并到模块中。

  • 这个初始值永不改变。

HeroDetailComponentprefix属性初始化为固定的字符串,而不是模板表达式。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 绑定。

考虑 ARIASVG 和 table 中的 colspan/rowspan 等 attribute。 它们是纯粹的 attribute,没有对应的属性可供绑定。

[attr.colspan]