前言
这篇介绍一些基本的 Angular 模板语法.
参考
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, 这世上有太多种模板语法了.
EJS, mustache, handlebars, JSX, Liquid, Razor
只能说各花入各眼吧. 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); } }
效果
- 组件 Component Template Angular Binding组件component template angular ng-template组件component template 组件component angular pipe component angular组件isolation 组件component elements angular component angular组件elements 组件component lifecycle angular template component compiling v-else-if standalone component angular component function template属性