Angular2 模板语法精粹之深入

Angular2 作为MVVM 模型-视图-视图模型框架,组件扮演着控制器或者视图模型的角色,模板则扮演视图的角色,熟练灵活的使用模板语法,可以最快速便捷的构建出复杂应用

本篇文章作为 Angular 模板语法总结的深入篇,涵盖了最通用的模板范例和原理,可以灵活的根据产品需求,搭建简洁有效的自定义模板


在 Angular 模版中,<script> 标签被禁用了,以防止脚本注入攻击的风险

通过自定义的组件和指令,可以扩展或者创建 html 标签,实现需求的视图功能


插值表达式


<h1>{{title}}</h1>

双花括号+模板表达式 构成了插值表达式的语法,可以把表达式的值赋予标签的属性或文本

<img src="{{imageSrc}}" />

模板表达式

模板表达式最终会计算出一个值,在插值表达式中使用的也是这个值,类似于 JavaScript 中的表达式,但是模版表达式禁用一些运算符和关键字

  • 赋值 =,+=,-= …

  • new 运算符

  • ;或,

  • ++ \ – 自增、自减

模板表达式的上下文就是引用这个模版的组件实例,不能引用 window、document,不能调用 console.log、Math.max

最佳实践

  • 模版表达式除了目标属性外,不因该改变应用的其它状态

  • 不要执行复杂的运算,因为模版表达式执行频繁

  • 不要耦合业务逻辑,简单易理解的绑定

  • 幂等性,在前置条件不变的条件下,最终结果唯一可确定

模版语句


用来响应绑定目标触发的事件

<button (click)="onSave($event)">Save</button>

语句上下文同样为组件实例

$event 代表触发事件的消息,对应 JS 中 event 对象


最佳实践

避免复杂的模版语句,通常止于组件实例方法调用或者属性赋值

绑定语法


数据绑定帮助我们简化从 DOM 元素中获取值和赋值的,通过使用 angular 定义的绑定语法,可以轻松实现 model 和 view 之间的映射关系,在模版中管理我们的数据流向

模版最为数据的消费者和生产者,可以帮助我们梳理和理解数据实际的含义,在模版中绑定属性和方法完全不必理会背后的处理和逻辑

数据方向 语法 场景
单向(组件 -> 模版) {{expression}},
[target]=”expression”,
bind-target=”expression”
插值表达式
属性 attr
类 class
样式 style
单向(模版 -> 组件) (target)=”statement”
on-target=”statement”
事件
双向 [(target)]=”expression”
bindon-target=”expression” | 双向

深入理解 HTML 和 DOM 关系


html 是一种标记语言,当我们使用 html 这种语言保存的 .html 文件在浏览器中打开时,浏览器根据我们在 html 中的描述,在浏览器中构建 DOM 树

总结:html 是一种描述,DOM 是 html 定义的,由浏览器生成的对象

所以,在 html 中定义的 attribute 属性会映射到浏览器生成的 DOM 对象的 property 上,但这种映射是单向的,只有在第一次渲染的时候,写在 html 标签中的 attribute 才会影响到 property,之后我们所有的操作都是基于 DOM 的 property 来实现的

<input type="text" value="Bob" />

此时,DOM value property = HTML value attribute

当用户在这个输入框中输入,”Sally” 时

DOM value property == “Sally”

HTML value attribute == “Bob”

所以,模板绑定是通过 property 和事件来生效的,attribute 只负责初始化,生成了 DOM 后,HTML 就可以靠边站了


绑定目标

数据绑定的目标可以是 (元素|组件|指令) 的 (property|事件)(绑定等式左侧的为目标名)

绑定场景 目标 例子
property 元素|指令|组件 属性 <img [src]="imageSrc" />
<hero-detail [hero]="currentHero"></hero-detail>
<div [ngClass]="{selected: isSelected}"></div>
事件 元素|组件|指令 事件 <button (click)="onClick($event)">Save</button>
<hero-detail [hero]="currentHero"></hero-detail>
<div (myClick)="clicked=$event">click me</div>
双向 事件与property <input [(ngModel)]="heroName" />
class class property <div [class.special]="isSpecial"></div>
style style property <div [style.color]="isSpecial? 'red': 'green'"></div>

property 绑定的注意事项

  • 属性绑定的数据是单向传输的,属性绑定无法从目标元素获取值

  • 元素属性的绑定最常见,但 angular 会优先匹配某个已知的指令的属性名(@Input)

    <div [ngClass]="classes">[ngClass] binding to the classes property</div>
    

    这里 ngClass 作为某个指令的属性来绑定

    指令属性冲突会发生什么?

    两个指令都会获取到绑定到值,而且都会被执行

  • bind-propertyName 规范形式

  • 保证单一功能原则,消除副作用

  • 如果没有加[],表达式会被当作字符串常量赋值给属性

  • 基于可读性考虑,推荐使用插值表达式来绑定属性(习惯问题,统一就好)


attribute 绑定

<tr><td colspan="{{1+1}}"></td></tr>
// 模版解析错误:colspan 不是已知的原生属性

解决方法:[attr.colspan]=”1+1” 特殊的语法支持


CLASS 绑定

可以添加和移除元素的 class 类名

<div [class]="classStr"></div>
<div [class.special]="isSpecial"></div>
// boolean

不如 ngClass 好用


STYLE 绑定

<div [style.color]="isSpecial?'red':'green'"></div>

不如 ngStyle 好用


事件绑定

响应用户和浏览器的动作,从元素到组件的数据传递

<button on-click="onClick($event)"></button>

同样,事件绑定也会优先匹配指令中输出的事件属性

  • $event 作为事件对象传递给事件的处理方法

$event 这里就是 DOM 原生的点击事件对象


EventEmitter 自定义事件

deleteRequest = new EventEmitter<Hero>();

delete() {

    this.deleteRequest.emit(this.hero);

}

这里定义了一个 EventEmitter 实例,即一个事件实例,当 delete() 指令时,触发了这个自定义的 deleteRequest 事件,同时

<hero-detail (deleteRequest)="deleteHero($event)"></hero-detail>

父级元素绑定了这个自定义事件,感知到事件触发并获取到了 this.hero 作为 $event,传递到自己的处理器中,完成了删除的动作


双向数据绑定

[(x)] 实际上是属性绑定和事件绑定的语法糖,使用的前提是绑定的目标同时具有 x 属性和 xChange 方法(名字必须一致)

<my-sizer [(size)]="fontSizePx"></my-sizer>

<div [style.font-size.px]="fontSizePx"></div>

等同于

<my-sizer [size]="fontSizePx" (sizeChange)="fontSizePx = $event"></my-sizer>

自定义事件参考上文

在这里,my-sizer 组件可以理解为一个黑箱,我们将 fontSizePx 绑定到这个黑箱的双向绑定接口上,在初始化的之后还可以不断获取到黑箱的输出,同时更新页面


表单的双向绑定

// 依赖 import { FormsModule } from '@angular/forms';

--- 

<input [(ngModel)]="firstName" />

// 等同于如下

<input [value]="firstName"
    (input)="firstName = $event.target.value" />

// 添加点佐料

<input [ngModel]="firstName"
    (ngModelChange)="setUpperCase(firstName)" />

**

前行的路上,感谢您的鼓励!!

**

猜你喜欢

转载自blog.csdn.net/lzch2105/article/details/53900429