[Angular] Day8. Templates and Text interpolation

前几天大概讲完了 Angular 的 Component 的基本功能与介绍,在很多例子中可以看到在 component.html 中使用了满多没看过的语法,比如 {{ value }}(clicl)="onClick()" 等等的,在前几天可能会对他觉得非常陌生,别担心接下来我们会对这些语法有详细的说明。

在 Angular 中,Templates 是一段 HTML,可以在 Templates 中使用特殊的语法来构建 Angular app的画面,那就让我们继续往下看吧。

https://ithelp.ithome.com.tw/upload/images/20210802/201247672iUKFGyC6V.png


Empower your HTML

在我们开发 Angular app 时,可以在 Templates 使用特殊的语法来扩展 HTML 的词汇表,举例来说可以在 Angular 通过内置模板函数、变量、event 和数据绑定,可以帮助你在开发过程中动态的获得和设置 DOM 的值。

虽然说 Angular 的 Template 是一段 HTML,但是所有的 templates 都只是整个网页的一部分,而不是整个页面,所以不需要在每一个 templates 中添加 <html><body><base> 之类的元素,而出於安全考量 Angular 也不允许在 templates 中加入 <script>


Text interpolation

介绍完什麽是 Templates 後接着要来介绍一些 templates 的语法,首先我们要介绍的是 Text interpolation,顾名思义就是将 component.ts 中的变量插入到 templates 中,当这个变量在 component.ts 中发生变化时,也会同步在 template 中发生变化,意味着画面也会跟着变化。

在默认情况下,插值是使用双花括号 {{}} 将插值夹在其中,来举个简单的例子:

  1. 首先先在 app.component.ts 中添加一个变量

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html'
    })
    export class AppComponent {
      currentCustomer = 'Fandix'
    }
    
  2. 在 app.component.html 中将这个值插入到 template 中

    <!-- app.component.html -->
    
    <h3>Current customer: {{ currentCustomer }}</h3>
    

https://ithelp.ithome.com.tw/upload/images/20210802/20124767SfgZjpfW0a.png

在画面可以看到确实有将 component.ts 当中的变量(currentCustomer)的内容呈现出来,那我们将变量的值更改一下

currentCustomer = 'Tako'

https://ithelp.ithome.com.tw/upload/images/20210802/20124767zWCwZTqGtJ.png
当 component.ts 中的变量内容改变後会动态的显示在画面中,这就是 Text interpolation 的用途。


Template expressions

可以在 template expressions 在双花括号中{{ }}产生一个值,Angular 会自动解析表达式并将解析过後的内容分配给绑定目标的属性,这个目标可以是 HTML Tag、Component selector 或 directive。

Resolving expressions with interpolation

一般来说在双花括号之间填入一个模板表达式的话,Angular 会先将他做计算,得到结果後将它转成字串并显示出来,举个简单的例子,透过差值将两个数字相加并呈现出来:

<!-- app.component.html -->

<h3>The sum of 1 + 1 is {{1 + 1}}</h3>

https://ithelp.ithome.com.tw/upload/images/20210802/20124767CF8r7xaM47.png

Angular 在 templates 的双花括号中收到了一个表达式,他会自动将这个表达式做计算,像上面的例子中的 1 + 1,得到结果後将它转成字串并显示出来,所以画面中会显示 1 + 1 = 2。

而表达式也可以调用这个 component.ts 中的 method,比如说:

  1. 在 app.component.ts 中新增一个 method

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html'
    })
    export class AppComponent {
      getValue() {
        return 'Fandix';
      }
    }
    
  2. 在 app.component.html 中将调用 method 的表达式填入到双花括号中

    <!-- app.component.html -->
    
    <h3>Hello {{ getValue() }}</h3>
    

https://ithelp.ithome.com.tw/upload/images/20210802/20124767dSHzApckq2.png

可以看到 Angular 在 template 调用了 component.ts 中的 method ,获得到的值将他呈现在画面中,而 Angular 在遇到差值时会执行以下的任务:

  1. 计算双花括号中的所有表达式
  2. 将表达式的结果转换为字串
  3. 将结果链接到任何相邻的文字字串
  4. 将组合分配给element 或 directive 属性

Syntas

一样的,要运用一个新的程序语言之前,需要先充分熟悉他的语法,不然会产生意料之外的错误喔,其实 templates expressions 的语法基本上都跟 Javascript expressions 一样,但是有几个特例:

  • 你不能使用有会产生 side effects 的 javascript expressions
    • 赋值(=, +=, -=, ...)
    • 运算符(new, typeof, instanceof)
    • 用分号(;)链结 expressions
    • 递增或递减运算符(++, --)
    • 还有一些 ES6 的运算符
  • 与 javascript 语法有明显差异的:
    • 不支援 bit 的运算符(|, &)
    • 新的 template expressions(|, ?, !, ...)

Preventing name collisions

介绍完如何将 component 中的变量插入 template 让画面随着变量动态改变後,要注意的是在使用这个功能时要防止名称冲突,因为当你使用了 Text interpolationt 插入变量後, Angular 对这个表达式的计算 context 是从 template variabledirectivecomponent member 的联合,所以当你插入了一个名称到 template 但这个名称在多个地方都有定义的话, Angular 会用以下的逻辑来确定 context:

  1. 在 template 中的变量名称 (ngFor 中的变量)
  2. 在 directive 中的 context 名称
  3. Component 中的变量名称

所以当你在使用 Text interpolationt 时尽量保持所有变量名称唯一,不然可能会被 shadowing 掉你原本想要呈现内容,我们举个例子:

这边先提早介绍 *ngFor,他也是使用在 template 当中,用法与 javascript 的 for loop 一样,当你的 component 中的变量是一个 arr 时,想要把这个 arr 中的数值都呈现在画面上就可以使用这个方法,一样举个简单的例子吧:

  1. 首先先在 app.component.ts 中宣告一个 arr 变数并将里面填上要呈现的内容。

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html'
    })
    export class AppComponent {
      displayArray = ['Hello', 'world', 'Angular', 'good'];
    }
    
  2. 接着在 app.component.html 中使用 *ngFor 将他们全部呈现在画面上

    <!-- app.component.html -->
    
    <div *ngFor="let content of displayArray">
        {{content}}
    </div>
    

https://ithelp.ithome.com.tw/upload/images/20210802/20124767Dasf05ADZV.png

在画面中可以看到透过 *ngFor 不断的递回将 displayArray 中的内容都显示出来,这边暂时介绍到这边,之後会更详细的介绍他的使用方法。

大概了解的 *ngFor 的使用方法後,将画面回到命名冲突,当你使用 *ngFor 命名迭代出来的每一个值得名称时要注意这个名称有没有在其他地方被引用到,如果有则会将其他相同名称的内容 shadowing 掉,举个小例子吧。

  1. 先在 app.component.ts 中定义两个变量

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html'
    })
    export class AppComponent {
      customers = [ 'Ebony', 'Chiho'];
      customer = 'Padma';
    }
    
  2. 在 app.component.html 中将这两个变量呈现在画面中

    <!-- app.component.html -->
    
    <div>
      <ul>
        <li *ngFor="let customer of customers">
    			<h1>Hello, {{ customer }}</h1>
    			{{ customer }}
    		</li>
      </ul>
    </div>
    

https://ithelp.ithome.com.tw/upload/images/20210802/20124767Gofwpc8OrA.png
在画面中可以看到,原本我们希望在每次迭代 customers 中的值时,都将 customer = 'Padma' 添加在上面,但是由於 *ngFor 中的变量 shadowing 了 customer 所以导致 'Padma' 无法呈现出来,所以在使用 Text interpolationt 插入变量时要注意有没有相同的名称喔!


结论

本篇中介绍了如何在 template 中插入 component 的变量以及该注意的事情,最後介绍几个在使用 Text interpolationt 时最好的设计规范以避免发生错误或是增加程序的可阅读性:

  • 使用简短的表达:尽可能使用 component 中 property 的名称或 method 调用。将应用程序和业务逻辑保留在 component 中而 template 只负责调用就可以,这样以便进行开发和测试。
  • 快速执行:Angular 会在在每个变更检测周期後执行模板表达式,许多非同步的行为都会触发变更检测周期,比如 Promise、HTTP 的结果、timer events、按键与滑鼠的移动等等,expression 应该快速的完成不然会让使用者体验下降,所以当需要进行长时间计算的事情时,请考虑使用缓存值。
  • 没有明显的 side effect:模板表达式不应该更改除了目标属性值之外的任何应用程序状态,读取 component 的值时不应更改到其他的显示值。

Reference


<<:  ASP.NET MVC 从入门到放弃 (Day3) -C#变数型态介绍

>>:  30天轻松学会unity自制游戏-制作子弹

Day06 UIKit 05 - 纯代码编写 Code

在开发前我们需要知道,在 iOS 中,我们可以采取 Storyboard、XIBs 或是纯 Code...

【Side Project】 (老板)订单清单-未完成餐点提示

原本程序的部分打算到上一篇就结束了, 不过有小夥伴问到如何在更改状态的同时<span>中...

你是谁、你的过去都不重要,成功的能力永远都从你开始。

你是谁、你的过去都不重要,成功的能力永远都从你开始。 It doesn’t matter who y...

DAY 8 『 CollectionView 』Part1

CollectionView:Storyboard、Xib + Collection View + ...

Day10 X 实作一个简单的 Virtualized List 吧!

Facebook、Instagram 应该都是我们日常生活中非常依赖的社群媒体了,每天闲来无事就要...