猿人旅程我爱编程

AngularJS 模板语法

2018-05-19  本文已影响5人  Junting

模板语法

模板生成流程图

模板是编写 Angular 组件最重要的一环,你至少需要深入理解以下知识点才能玩转 Angular 模板:

  1. 对比各种 JS 模板引擎的设计思路
  2. Mustache(八字胡)语法, {}
  3. 模板内的局部变量
  4. 属性绑定、事件绑定、双向绑定
  5. 在模板里面使用结构型指令 ngIf、ngFor、ngSwitch
  6. 在模板里面使用属性型指令 NgClass、NgStyle、NgModel
  7. 在模板里面使用管道格式化数据

对比各种 JS 模板引擎的设计思路

什么是模板引擎? 是指利用某种模板语言将页面制成模板,再依据业务逻辑将该模板语言翻译成业务数据,从而生成最终展示页面。 简单的讲就是根据静态HTMl元素和业务逻辑处理的数据结合渲染生成浏览器器需要的页面。

各种模板引擎的唯一目标就是提高开发效率、缩短时间成本。综合来说,无论是哪一种前端模板,大家都比较推崇“轻逻辑”( logic-less )的设计思路。

何为“轻逻辑”? 简而言之,所谓“轻逻辑”就是说,你不能在模板里面编写非常复杂的 JavaScript 表达式。比如,Angular 的模板语法就有规定:

为什么要“轻逻辑”?

  1. 本身的 Html 是不识别 if 、for 等操作的;模板引擎处于的地位就是帮忙编译转换纯HTMl元素。
  2. 在 HTML 加入复杂的逻辑,会加大模板引擎编译的时间和计算能力;而且也不建议复杂逻辑处理放到HTMl里来做,保证 HTML 的单一纯洁性;使用模板也是来做简单的插值相关的操作
  3. JS 版的编译器需要在浏览器里面运行,搞得太复杂浏览器拖不动!
  4. 最根本还是模板引擎不够强, 并不是万能的;

对于 Angular 来说,强调“轻逻辑”还有另一个原因:在组件的整个生命周期里面,模板函数会被执行很多次。你可以想象, Angular 每次要刷新组件的外观的时候,都需要去调用一下模板函数,如果你在模板里面编写了非常复杂的代码,一定会增加渲染时间,用户一定会感到界面有“卡顿”。

人眼的视觉延迟大约是100ms到400ms之间,如果整个页面的渲染时间超过400ms,界面基本上就卡得没法用了。有一些做游戏的开发者会追求60fps刷新率的细腻感觉,60分之1秒约等于16.7ms,如果 UI 整体的渲染时间超过了16.7ms,就没法达到这个要求了。

轻逻辑( logic-less )带来了效率的提升,也带来了一些不方便,比如很多模板引擎都实现了 if 语句,但是没有实现 else,所以开发者们在编写复杂业务逻辑的时候模板代码会显得非常啰嗦。

目前来说,并没有完美的方案能同时兼顾运行效率和语法表现能力,这里只能取一个平衡。

Mustache 语法

Mustache 语法也就是你们说的双花括号语法{{...}}。

关于 Mustache 语法,你需要掌握3点:

  1. 它可以获取到组件里面定义的属性值。
  2. 它可以自动计算简单的数学表达式,例如:加减乘除、取模
  3. 它可以获得方法的返回值。

插值语法关键代码实例:

<h3>
    欢迎来到{{title}}!
</h3>
public title = 'Mustache 语法';

简单的数学表达式求值:

<p>1 + 5 = {{ 1 + 5 }}</p>

调用组件里面定义的方法:

<p> {{ getStr() }} </p>
public getStr(): string {
    return '调用方法!'
}

属性绑定([属性名])

属性绑定是用方括号来做的,写法:

<img [src]="imgSrc" />
<button [disabled]="isUnchanged">是否禁用</button>
public imgSrc:string = './images.png';
public isUnchanged:boolean = true;

很明显,这种绑定是单向数据绑定,单一的读取值而已。

事件绑定 ( (事件名) )

事件绑定是用圆括号来做的,写法:

<button (click)="btnClick($event)">点击事件</button>
pubic btnClick(e):void {
    alert('点击事件测试~');
}

双向绑定 ( [(...)] )

你经常需要显示数据属性,并在用户作出更改时更新该属性。

在元素层面上,既要设置元素属性,又要监听元素事件变化。

双向绑定是通过方括号里面套一个圆括号 [(...)] 来做的,模板写法:

<app-sizer [(size)]="fontSizePx"></app-sizer>
public fontSizePx:number = 14;

模板内的局部变量

在模板里面使用结构型指令

Angular 有3个内置的结构型指令:*ngIf*ngForngSwitchngSwitch 的语法比较啰嗦,使用频率小一些, 了解就好。

*ngIf 代码实例:

<p *ngIf="isShow">显示还是不显示?</p>
<button (click)="toggleShow()">控制显示隐藏</button>
public isShow:boolean=true;

public toggleShow():void {
    this.isShow = !this.isShow;
}

*ngFor 代码实例:

<ul>
    <li *ngFor="let item of items; let i = index;">
        {{i+1}} - {{ item.name }}
    </li>
</ul>
public items:Array<any>=[
    {name:"PyCoder"},
    {name:"Jun ting"},
    {name:"EcmaScript"}
];

*ngSwitch 代码实例:

<div [ngSwitch]="mapStatus">
    <p *ngSwitchCase="0">下载中...</p>
    <p *ngSwitchCase="1">正在读取...</p>
    <p *ngSwitchDefault>系统繁忙...</p>
</div>
public mapStatus:number = 1;

特别注意:一个 HTML 标签上只能同时使用一个结构型的指令。

因为“结构型”指令会修改 DOM 结构,如果在一个标签上使用多个结构型指令,大家都一起去修改 DOM 结构,到时候到底谁说了算?

那么需要在同一个 HTML 上使用多个结构型指令应该怎么办呢?有两个办法:

在模板里面使用属性型指令

使用频率比较高的3个内置指令是:NgClassNgStyleNgModel

NgClass 使用案例代码:

<div [ngClass]="currentClasses">同时批量设置多个样式</div>
<button (click)="setCurrentClasses()">设置</button>
public currentClasses: [];

public canSave: boolean = true;
public isUnchanged: boolean = true;
public isSpecial: boolean = true;

public setCurrentClasses ():void {
    this.currentClasses = {
        'saveable': this.canSave,
        'modified': this.isUnchanged,
        'special': this.isSpecial
    }
}
上一篇 下一篇

猜你喜欢

热点阅读