模版表达式
{{ expression }}
表达式可以是大多数JS表达式,但不能包含赋值等修改操作。
表达式的运行上下文通常是组件实例。变量的优先级为模版变量 > 指令名称 > 组件属性。模版表达式只能引用表达式上下文的成员,不能引用全局命名空间中的内容,如document,(可能是为了强制关注点分离吧,类比之下Razor是可以用的,只是不推荐)
表达式原则
- 没有明显副作用:除目标属性外不改变任何状态,这对Angular的“单向数据流”策略至关重要,在读取组件值时不应该担心会改变其他值。
- 快速执行:Angular在每个更改检测周期后执行表达式,表达式执行很慢会影响用户体验
- 简单:尽可能将逻辑在组件中编写,更容易开发测试
- 幂等:依赖项不变的话,则返回完全相同的东西(多次调用返回同一个引用)
模版语句
(event)="statement"
模版语句具有“副作用”,是响应事件,改变其他状态
模版语句和模版表达式
数据绑定
绑定方向
- 从数据源到视图:
{{expression}}
[target]="expression"
bind-target="expression"
- 从视图到数据源
(target)="statement"
on-target="statement"
- 双向绑定
[(target)]="expression"
bindon-target="expression"
使用properties
进行数据绑定后,实际不再设置HTML属性(attribute),而是关注DOM属性(property)
attributes由HTML定义,properties由DOM定义。attributes和properties直接的映射关系有些混乱,如id等一对一映射的,colspan等只有attribute的,textContent等只有property的。attributes有时只负责初始值,有时也会令人迷惑。
所以数据绑定绑定的是properties和events,不包括attributes。
在Angular中,attributes的唯一作用是初始化元素和指令状态。
绑定目标
type | target |
---|---|
property | Element property\Component property\Directive property |
event | Element event\Component event\Directive event |
two-way | Event and property |
attribute | Attribute (the exception) |
class | class property |
style | style property |
Property绑定
{{}}
在处理字符串时比较直观,但在绑定其他类型时必须使用[]
属性绑定不允许使用<script></script>
,以增强安全性
Attribute绑定
当一个HTML元素的attribute没有对应的property时,必须采用attribute绑定
<table border=1>
<!-- expression calculates colspan=2 -->
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
<!-- ERROR: There is no `colspan` property to set!
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
-->
<tr><td>Five</td><td>Six</td></tr>
</table>
主要用途之一是设置ARIA属性(针对障碍人士的辅助)
event绑定
使用EventEmitter
来自定义事件
内置attribute指令
- NgClass CSS类的集合,绑定到一个js对象
- NgStyle HTML样式的集合…一般会直接操作这个吗?
- NgModel 表单元素的双向绑定,实际是一种语法糖,ngModelChange事件监听属性更改
内置结构指令
- 在结构指令前加上“*”
在一个元素中只能使用一个结构指令
ngIf
ngFor
在操作大量列表时可能很卡,通过trackBy
属性来改善性能ngSwitch
<div [ngSwitch]="currentHero.emotion">
<app-happy-hero *ngSwitchCase="'happy'" [hero]="currentHero"></app-happy-hero>
<app-sad-hero *ngSwitchCase="'sad'" [hero]="currentHero"></app-sad-hero>
<app-confused-hero *ngSwitchCase="'confused'" [hero]="currentHero"></app-confused-hero>
<app-unknown-hero *ngSwitchDefault [hero]="currentHero"></app-unknown-hero>
</div>
模版引用
在模版中创建一个引用,用于获取模版元素的值
<input #phone placeholder="phone number">
<!-- lots of other elements -->
<!-- phone refers to the input element; pass its `value` to an event handler -->
<button (click)="callPhone(phone.value)">Call</button>
可以使用ref-
前缀代替#
Input/Output
用于在组件间传值
通常Input的为一个值,Output的为一个事件,可以为事件创建别名
管道
……
?.
, !.
, $any
“?.”安全导航操作符
用于检测属性路径中的空值,当有空值时显示空白,用于避免错误
<!-- No hero, no problem! -->
The null hero's name is {{nullHero?.name}}
“!.” 非空断言操作符
断言值一定是非空的。在开启严格空值检测时使用,否则可选
<!--No hero, no text -->
<div *ngIf="hero">
The hero's name is {{hero!.name}}
</div>
“$any” 类型转换函数
可以跳过是否有某成员属性的检查
<!-- Accessing an undeclared member -->
<div>
Undeclared members is {{$any(this).member}}
</div>