Angular 在哪里定义 *ngIf 的 "as local-var" 行为?
Where does Angular define "as local-var" behavior for *ngIf?
我想了解 ngIf 的 "as local-var" 可选行为在哪里定义,例如:
*ngIf="user$ | async as user"
尝试查看源代码中明显的地方,例如
https://github.com/angular/angular/blob/master/packages/common/src/directives/ng_if.ts
但代码中没有任何内容,只有文档。
有谁知道这个魔法发生在代码的什么地方?
是的,这是在模板编译过程中发生的魔法。
下面的模板
<div *ngIf="user$ | async as user"></div>
只是糖分:
<ng-template [ngIf]="user$ | async" let-user="ngIf">
<div></div>
</ng-template>
所以答案:以下字符串将值传递给此变量:
this._context.$implicit = this._context.ngIf = condition;
^^^^^^^^^^^^^
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);
}
}
并像这样使用它:
<ng-template [ngVar]="true" let-x="ngVar"><div>{{x}}</div></ng-template>
或
<div *ngVar="true as x">{{x}}</div>
有什么魔力?
如果你想了解编译器的神奇之处,那么让我们看一个例子:
<div *ngVar="true as x"></div>
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
2) HtmlParser
基于这些标记创建元素的树:
Element div
attrs: name: *ngIf
value: true as x
3) TemplateParser
构建AST(抽象语法节点)树。为此 TemplateParser
使用名为 TemplateParseVisitor
的特殊访问者
此访问者遍历了上一步中收到的所有树。让我们看看当编译器到达 visitElement:
时它是如何工作的
所以我们可以看到任何具有结构指令的模板,例如:
*dir="someValue as someVar"
代表如下:
<ng-template [dir]="someValue" let-someVar="dir">
另请参阅:
我想了解 ngIf 的 "as local-var" 可选行为在哪里定义,例如:
*ngIf="user$ | async as user"
尝试查看源代码中明显的地方,例如 https://github.com/angular/angular/blob/master/packages/common/src/directives/ng_if.ts
但代码中没有任何内容,只有文档。
有谁知道这个魔法发生在代码的什么地方?
是的,这是在模板编译过程中发生的魔法。
下面的模板
<div *ngIf="user$ | async as user"></div>
只是糖分:
<ng-template [ngIf]="user$ | async" let-user="ngIf">
<div></div>
</ng-template>
所以答案:以下字符串将值传递给此变量:
this._context.$implicit = this._context.ngIf = condition;
^^^^^^^^^^^^^
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);
}
}
并像这样使用它:
<ng-template [ngVar]="true" let-x="ngVar"><div>{{x}}</div></ng-template>
或
<div *ngVar="true as x">{{x}}</div>
有什么魔力?
如果你想了解编译器的神奇之处,那么让我们看一个例子:
<div *ngVar="true as x"></div>
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
2) HtmlParser
基于这些标记创建元素的树:
Element div
attrs: name: *ngIf
value: true as x
3) TemplateParser
构建AST(抽象语法节点)树。为此 TemplateParser
使用名为 TemplateParseVisitor
此访问者遍历了上一步中收到的所有树。让我们看看当编译器到达 visitElement:
时它是如何工作的所以我们可以看到任何具有结构指令的模板,例如:
*dir="someValue as someVar"
代表如下:
<ng-template [dir]="someValue" let-someVar="dir">
另请参阅: