Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
511 views
in Technique[技术] by (71.8m points)

rxjs - Where does Angular 4 define "as local-var" behavior for *ngIf?

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 into obvious places in source, like https://github.com/angular/angular/blob/master/packages/common/src/directives/ng_if.ts

But nothing in the code, only docs.

Does anyone know where in the code this magic is happening ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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:

enter image description here

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:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...