快捷搜索:  汽车  科技

angular编程教程:七爪源码Angular结构指令及其微语法

angular编程教程:七爪源码Angular结构指令及其微语法现在,在 <ng-template> 中放置一个指令,你就有了一个结构指令:但是当你将它包装在 <ng-template><div><p>Text</p></div></ng-template> 中时,你是在告诉 Angular “_declare div 标签的结构,使用 一个段落标签,带有字符串“Text”_”。 但请注意,现在我们并没有告诉 Angular 渲染它。模板是结构让我们开始定义它是什么。结构指令是具有结构的指令。 该结构是一个 ng 模板。 当你编写 <div><p>Text</p></div> 时,你是在告诉 Angular “_declare div 标签的结构,带有一个段落标签,带有字符串“Text”,并渲染它_” .

Angular 结构指令及其微语法

angular编程教程:七爪源码Angular结构指令及其微语法(1)

你有没有想过 *ngIf 和 *ngFor 的星号前缀是什么? 这称为结构性指令。

在本文中,我将向您展示您何时需要它以及它是如何工作的。

我还将做第 2 部分,向您展示如何创建自己的结构指令。

模板是结构

让我们开始定义它是什么。

结构指令是具有结构的指令。 该结构是一个 ng 模板。 当你编写 <div><p>Text</p></div> 时,你是在告诉 Angular “_declare div 标签的结构,带有一个段落标签,带有字符串“Text”,并渲染它_” .

但是当你将它包装在 <ng-template><div><p>Text</p></div></ng-template> 中时,你是在告诉 Angular “_declare div 标签的结构,使用 一个段落标签,带有字符串“Text”_”。 但请注意,现在我们并没有告诉 Angular 渲染它。

现在,在 <ng-template> 中放置一个指令,你就有了一个结构指令:

<ng-template [ngIf]="condition"><div><p>Text</p></div></ng-template>

合成糖

这就是 ngIf 的工作原理。 Angular 解析 <ng-template>,生成一个 TemplateRef,它被注入到 NgIf 指令中。如果传递给 ngIf 的条件为真,则呈现模板。

但是每次我们想使用 NgIf 或任何其他需要 ng-template 的指令时创建一个 ng-template 会很烦人。所以 Angular 团队创造了合成糖。就像一条捷径。

当您在指令前加上星号时,Angular 会将其包装在 ng-template 中并将指令应用于 ng-template。所以<div *ngIf=“condition”>Abc</div>,变成<ng-template [ngIf]=“condition”><div>Abc</div></ng-template>

这只是合成糖。如果您愿意,您可以编写不带星号前缀的整个应用程序。

只允许一个

了解了它的工作原理,您现在可以理解为什么我们只能对每个元素使用一个结构指令。如果你在同一个元素中使用 *ngIf 和 *ngFor,Angular 会如何去糖呢?先 ngIf 再 ngFor?相反?两者都在同一个模板中?

微语法

说到ngFor,好像比ngIf要复杂的多吧?我见过一些非常复杂的 ngFor 表达式,比如传递一个 trackBy 函数,管道一个 observable 数组,获取索引,并检查它是否是最后一个元素。

<div *ngFor="let item of list$ | async; trackBy: trackByFn; let itemIndex = index; let islast = last">{{ item }}</div>

最初,我认为这是 ngFor 特有的术语,但事实并非如此。 这是一个完整记录的语法,适用于任何结构指令,甚至是您最终创建的指令。 它被称为“结构指令微语法”。 (有点明显)

结构指令微语法将表达式用分号 (;) 分开。 在我们的 NgFor 示例中,我们有 4 个表达式:

  1. 让列表项$ | 异步
  2. trackBy:trackByFn
  3. 让 itemIndex = 索引
  4. 让 islast = 最后

声明

以 let 开头的表达式是变量声明。 您在 let 之后立即声明变量名称,并使用等号 (=) 将其指向导出指令上下文中的变量名称。

那是很多,对不起。

我的意思是当我们渲染一个 <ng-template> 时,我们可以选择传递一个上下文对象。 并且这个上下文对象的属性被传递给模板。 上下文对象可以有多个显式变量和一个隐式变量。

<!-- Rendering an <ng-template> with a context object --> <ng-container *ngTemplateOutlet="templateExample; context: { $implicit: 'test' index: 1 }"></ng-container> <!-- Using the context properties in the <ng-template> --> <ng-template #templateExample let-itemIndex="index" let-item> <p>#{{ itemIndex }} - {{ item }}</p> </ng-template>

它就像一个 JavaScript 函数,我们有参数,我们声明了它,因此非常显式,我们有 this,它是一个隐式变量,即使我们没有声明它也存在。

function example(itemIndex isLast) { // Explicit console.log(itemIndex isLast); // Implicit console.log(this); }

在一个函数中,你可以有任意多的参数,但只有一个 this。 就像这样,在 ng-template 中,您可以拥有任意数量的显式变量,但只有一个隐式变量。

当你不指向任何导出的变量时,你会得到隐式变量。 例如,let item 正在获取隐式变量。 但是让 isLast = last 得到显式的最后一个变量,让 itemIndex = index 得到显式的索引变量。

对变量进行脱糖处理后,我们得到:

<ng-template let-item let-itemIndex="index" let-isLast="last"> <p>#{{ itemIndex }} - {{ item }}</p> <p *ngIf="isLast">The end</p> </ng-template>

关键表达式

带有两个参数和它们之间的可选冒号 (:) 的表达式是键表达式。 表达式(右侧)被分配给前面带有前缀的键(左侧)。

让我们看一些例子。

在 \*ngIf="condition; else otherTemplate 中,对于 else otherTemplate 表达式:

  • ngIf 是前缀
  • 否则是关键
  • otherTemplate 是表达式

angular编程教程:七爪源码Angular结构指令及其微语法(2)

这被脱糖为 <ng-template [ngIfElse]="otherTemplate"></ng-template>

angular编程教程:七爪源码Angular结构指令及其微语法(3)

在 *ngFor="let item of list; trackBy: trackByFn,对于 trackBy: trackByFn 表达式:

  • ngFor 是前缀
  • trackBy 是关键
  • trackByFn 是表达式

这被脱糖为 <ng-template [ngForTrackBy]="trackByFn"></ng-template>

此外,对于那个 NgFor example,list 的 let item 中的 list 也是一个关键表达式。

  • ngFor 是前缀
  • of 是关键
  • 列表是表达式

这被脱糖为 <ng-template [ngForOf]="list"></ng-template>

本地绑定

最后要提到的是表达式末尾的可选 as 关键字。 它声明一个模板变量并将表达式的结果映射到它。

*ngIf="condition as value" 变为 <ng-template [ngIf]="condition" let-value="ngIf">

angular编程教程:七爪源码Angular结构指令及其微语法(4)

angular编程教程:七爪源码Angular结构指令及其微语法(5)

结论

而已。 您现在了解了结构指令的工作原理以及如何分析它们的微语法。

我将写另一篇文章,介绍如何从头开始编写自定义结构指令以及如何告诉 Angular 编译器对其上下文进行类型检查。

祝你有美好的一天,很快见到你!

猜您喜欢: