Angular 复习与进阶系列 – Component 组件 の Template Binding Syntax

发布时间 2023-04-06 16:51:14作者: 兴杰

前言

这篇介绍一些基本的 Angular 模板语法.

 

参考

Docs – Understanding binding

 

Render, Event Listening and DOM Manipulation

Angular 作为一个 MVVM 框架, 有两个任务是一定要处理好的

1. First Render

2. Event Listening & DOM Manipulation

Render Engine

First Render 的工作是把 data 和 template 做 binding and render, 这世上有太多种模板语法了.

EJSmustachehandlebarsJSXLiquidRazor

只能说各花入各眼吧. Angular 也整了一套自己独一无二的语法. 不像 JSX 和 Razor 那样, 直接把 JS / C# 结合 HTML,

Angular 的思想是尽可能不去破坏 Native HTML 的规则. 尽可能少的去加入新语法 (虽说尽可能少, 但其实并不少...)

Event Listening & DOM Manipulation

除了 first render, 用户交互也是避不开的, 监听事件, 修改 DOM 也是一个 MVVM 框架的任务.

 

常用的 Template Binding Syntax

我先介绍一些简单和常用的, 先大概过一遍, 体会一下, 下一章节我们再 focus 一些比较负责的.

常见的 DOM Manipulation 有

const element = document.querySelector<HTMLElement>('.selector')!;
element.textContent = 'value'; // update text
element.title = 'title'; // update property
element.setAttribute('data-value', 'value'); // set attribute (note: attribute and property are not the same thing)
element.style.padding = '16px'; // change style
element.classList.add('new-class'); // add class

const headline = document.createElement('h1');
headline.textContent = 'Hello World';
element.appendChild(headline); // append a element
element.innerHTML = `<h1>Hello World</h1>`; // write raw HTML

element.addEventListener('click', () => console.log('clicked')); // listen and handle a event

Text Binding

<h1>{{ value }}</h1>

value 来自组件的 property

Property Binding

<h1 [title]="value">Hello World</h1>
<h1 [title]="'Hello World'">Hello World</h1>
<h1 [title]="(100 - 10 === 90) ? 'Hello World' : 'Hello Kitty'">Hello World</h1>

当左边是 [放括弧], 右边的输入就变成了 JavaScript expression (不是所有 expression 都支持)

第一行 value 是 binding with component property

第二行是 hardcode 一个 string. 注意它有 quote. 因为是 JavaScript expression.

第三行是一个复杂的 expression (注: 虽然 Angular 允许写 expression, 但是尽量不要把逻辑放到 HTML, 这会让 HTML 看上去很乱水)

Attribute Binding

<h1 [attr.data-value]="value">Hello World</h1>

和 property 写法一样, 只是前面加了 prefix attr. 

attribute 和 property 是不同的东西哦, 如果你不知道, 请看这篇 Attribute 和 Property 的区别.

Style Binding

<!-- single style + declare unit in property side -->
<h1 [style.padding.px]="value">Hello World</h1>

<!-- declare unit in value side -->
<h1 [style.padding]="'16px'">Hello World</h1>

<!-- multiple style property declare -->
<h1 [style.padding.px]="16" [style.width]="'100px'">Hello World</h1>

<!-- multiple style by passing object -->
<h1 [style]="{ padding : '16px', width: '100px' }"></h1>

<!-- Error: declare unit in property side won't work when using passing object mode -->
<h1 [style]="{ 'padding.px' : 16, width: '100px' }"></h1>

<!-- use value null or undefined to remove the specify style -->
<h1 [style]="{ padding : null, width: '100px' }"></h1>

上面给的例子很多是 hardcode, 这个是为了我方便写, 全部都可以改成 link with component property 的.

style 写法蛮多的, 但常用的是第一种而已,

[style]="object" 这个写法不好, 它不支持 .px suffix 而且修改 property 是不会 re-render 的, 只有给予整个全新的 object 才会 re-render (简单说, 就是要 immutable object)

所以 best practice 是用 ngStyle 指令来做 multiple style (这个下面会详细讲).

Class Binding

<!-- if value true, then class will be added -->
<h1 [class.my-class]="true">Hello World</h1>

<!-- use object for multiple -->
<h1 [class]="{ 'my-class' : true, 'second-class': true }">Hello World</h1>

<!-- use array -->
<!-- note: value should not be null or undefined, empty string is ok -->
<h1 [class]="['my-class', 'second-class']">Hello World</h1>

<!-- use string -->
<h1 [class]="'my-class second-class'">Hello World</h1>

和 style binding 一样, [class]="object | array" 同样要求 immutable for re-render

for multiple class, best practice 是使用 ngClass 指令.

Event Listening

<button (click)="doSomething($event)">Click Me</button>
<input (keydown)="doSomething($event)">
<!-- 还可以指定只监听某个 key 哦 -->
<input (keydown.space)="doSomething($event)">
<input (keydown.enter)="doSomething($event)">
<input (keydown.shift.a)="doSomething($event)">

<!-- conditional execute -->
<input (keydown)="(100 - 10 === 90) ? doSomething($event) : doSomethingElse($event)">
<input (keydown)="(100 - 10 === 90) && doSomething($event)">

监听事件用的 (元括弧), 右边依然是 JavaScript expression

doSomething 是 component method, $event 是一个特殊关键字. 它代表了这个事件监听 emit / dispatch 的 event

for click 的话是 MouseEvent, keydown 则是 KeyboardEvent

export class AppComponent {
  doSomething(event: MouseEvent | KeyboardEvent) {
    console.log(event);
  }
}

效果