Where does Angular 4 define “as local-var” behavior for *ngIf?

后端 未结 1 2011
失恋的感觉
失恋的感觉 2020-12-05 16:32

I am trying to understand where is the \"as local-var\" optional behavior of ngIf defined, e.g.: *ngIf=\"user$ | async as user\"

Tried looking

相关标签:
1条回答
  • 2020-12-05 17:12

    Yeah, it's magic that happens during template compilation.

    The template below

    <div *ngIf="user$ | async as user"></div>
    

    is just sugar for:

    <ng-template [ngIf]="user$ | async" let-user="ngIf">
      <div></div>
    </ng-template>
    

    So the answer: the following string passes value to this variable:

    this._context.$implicit = this._context.ngIf = condition;
                                    ^^^^^^^^^^^^^
    

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

    For example we can create structural directive 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);
      }
    }
    

    and use it either like:

    <ng-template [ngVar]="true" let-x="ngVar"><div>{{x}}</div></ng-template>
    

    or

    <div *ngVar="true as x">{{x}}</div>
    

    What's the magic?

    If you want to understand where is the magic in compiler then let's take a look at an example:

    <div *ngVar="true as x"></div>
    

    1) Angular compiler tokenizes this string like:

    <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 creates element's tree based on these tokens:

    Element div
           attrs: name:  *ngIf
                  value: true as x
    

    3) TemplateParser builds AST(abstract syntax node) tree. To do this TemplateParser uses special visitor called TemplateParseVisitor

    This visitor goes through all tree received in the previous step. And let's look at how it works when compiler comes to visitElement:

    So as we can see any template with structural directive like:

    *dir="someValue as someVar"
    

    represents the following:

    <ng-template [dir]="someValue" let-someVar="dir">
    

    See also:

    • https://alexzuza.github.io/enjoy-ng-parser/
    • Angular2: How is ngfor expanded
    • How to declare a variable in a template in Angular2
    0 讨论(0)
提交回复
热议问题