Angular 4在哪里为*ngIf定义"as local-var"行为?

c69*_*c69 6 open-source rxjs angular

我试图了解ngIf定义的"as local-var"可选行为在哪里,例如: *ngIf="user$ | async as user"

尝试在源代码中查看明显的位置,例如 https://github.com/angular/angular/blob/master/packages/common/src/directives/ng_if.ts

但代码中没有任何内容,只有文档.

有没有人知道这个魔法发生在代码中的哪个位置?

yur*_*zui 15

是的,这是模板编译过程中发生的神奇之处.

下面的模板

<div *ngIf="user$ | async as user"></div>
Run Code Online (Sandbox Code Playgroud)

只是糖:

<ng-template [ngIf]="user$ | async" let-user="ngIf">
  <div></div>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

所以答案是:以下字符串将值传递给此变量:

this._context.$implicit = this._context.ngIf = condition;
                                ^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

https://github.com/angular/angular/blob/master/packages/common/src/directives/ng_if.ts#L115

例如,我们可以创建结构指令ngVar:

@Directive({
  selector: '[ngVar]',
})
export class VarDirective {
  @Input()
  set ngVar(context: any) {
    this.context.$implicit = this.context.ngVar = context;
                              ^^^^^^^^^^^^^^^^
    this.updateView();
  }

  context: any = {};

  constructor(private vcRef: ViewContainerRef, private templateRef: TemplateRef<any>) {}

  updateView() {
    this.vcRef.clear();
    this.vcRef.createEmbeddedView(this.templateRef, this.context);
  }
}
Run Code Online (Sandbox Code Playgroud)

并使用它像:

<ng-template [ngVar]="true" let-x="ngVar"><div>{{x}}</div></ng-template>
Run Code Online (Sandbox Code Playgroud)

要么

<div *ngVar="true as x">{{x}}</div>
Run Code Online (Sandbox Code Playgroud)

什么是魔术?

如果你想了解编译器的神奇之处,那么让我们来看一个例子:

<div *ngVar="true as x"></div>
Run Code Online (Sandbox Code Playgroud)

1)Angular编译器将此字符串标记为:

<div *ngVar="true as x"></div>
 (1)   (2)      (3)   (4) (5)


(1) - TAG_OPEN_START
(2) - ATTR_NAME
(3) - ATTR_VALUE
(4) - TAG_OPEN_END
(5) - TAG_CLOSE
Run Code Online (Sandbox Code Playgroud)

2)HtmlParser根据这些标记创建元素树:

Element div
       attrs: name:  *ngIf
              value: true as x
Run Code Online (Sandbox Code Playgroud)

3)TemplateParser构建AST(抽象语法节点)树.为此,TemplateParser使用名为TemplateParseVisitor的特殊访问者

此访问者将浏览上一步中收到的所有树.让我们来看看当编译器访问visitElement时它是如何工作的:

在此输入图像描述

因此,我们可以看到任何带有结构指令的模板,如:

*dir="someValue as someVar"
Run Code Online (Sandbox Code Playgroud)

代表以下内容:

<ng-template [dir]="someValue" let-someVar="dir">
Run Code Online (Sandbox Code Playgroud)

也可以看看:

  • 这太棒了。但我就是不明白为什么它不在框架中。而且我必须相信它不存在是有原因的 - 就像它可能不适用于更改检测或其他一些类似的奇怪现象。需要这样的功能是否意味着我们在模板之外做了一些根本性的错误?或者我们都应该使用这个? (2认同)