Angulars结构指令的确切语法是什么

时间:2019-05-09 15:00:05

标签: angular angular-template

角度documentation解释说,诸如<p *ngIf="a as b"></p>之类的结构性指令已“减少”到<p [ngIf]="a" [ngIfAs]="b">中。

杜绝使用microsyntax,允许像

这样的表达式
let node; when: hasChild
a as b
let x of y; index = i; trackBy: f

该文档提供了一些微语法的示例,并建议研究ngIf的来源,但未提供正式定义。

angular的结构指令的微语法是什么语法?

2 个答案:

答案 0 :(得分:0)

根据文档,以下代码:

<div *ngIf="hero" class="name">{{hero.name}}</div>

变成:

<ng-template [ngIf]="hero">
  <div class="name">{{hero.name}}</div>
</ng-template>

Angular在您的div周围创建此ng-template标记,并在决定是否添加div之前评估if。 ng-template是一个phantom标记,它在DOM中不存在(不会打扰CSS),并且具有一定的逻辑。

答案 1 :(得分:0)

首先,您可以签出我的interactive DEMO

enter image description here

那么,这里的逻辑是什么?

一旦Angular遇到结构指令,它就会尝试解析它:

 *dir="..."
/\
indicates that it's a structural directive

一开始有3种情况:

*dir="expr
       \/
   [dir]="expr"

*dir="let var  // also var can have value
       \/ // starts with keyword 'let', indicates variable
   [dir] let-x="$impicit"


*dir="as var
      \/ // starts with keyword 'as'
  let-x="$impicit" // it won't fail but your directive won't be instantiated

在表达式之后,您可以使用as关键字来为该表达式定义模板输入变量,也可以使用诸如空格,冒号,分号或逗号之类的分隔符:

*dir="expr as var
 \/
[dir]="exp" let-var="dir"

*dir="expr[ ]
*dir="expr:
*dir="expr;
*dir="expr,

请注意,dir在这里被视为第一个模板绑定键。

现在该到另一个键或变量了:

*dir="expr key2
*dir="expr:key2
*dir="expr;key2
*dir="expr,key2

我们可以通过空格或分号为该键分配值:

*dir="expr key2 exp2
*dir="expr:key2 exp2
*dir="expr;key2 exp2
*dir="expr,key2 exp2
or
*dir="expr key2:exp2

这样,我们可以产生其他密钥。这些密钥大写并与第一个密钥连接。

*dir="expr key2 exp2 key3 exp3 ...
\/
[dir]="expr " [dirKey2]="exp2 " [dirKey3]="exp3"


let node; when: hasChild; otherKey: otherValue
  \/       \/      \/
  var     key    value
                         \/
dir [dirWhen]="hasChild" [dirOtherKey]="otherValue" let-node="$implicit"


*dir="let x of y; index = i; trackBy: f"
           \/
dir [dirOf]="y" [dirIndex]="= i" [dirTrackBy]="f" let-x="$implicit"

*dir="let x  of   y;  let index = i; trackBy: f"
        \/   \/   \/      \/           \/    \/
        var  key  value     var          key   value
                   \/
dir [dirOf]="y" [dirTrackBy]="f" let-x="$implicit" let-index="i"

如您所见,我们可以定义键值,也可以通过let或将keywords设置为template input variables

如果您认为Angular文档没有完全解释它,则可以遵循the source code

  // Parses the AST for `<some-tag *tplKey=AST>`
  parseTemplateBindings(tplKey: string): TemplateBindingParseResult {
    let firstBinding = true;
    const bindings: TemplateBinding[] = [];
    const warnings: string[] = [];
    do {
      const start = this.inputIndex;
      let rawKey: string;
      let key: string;
      let isVar: boolean = false;
      if (firstBinding) {
        rawKey = key = tplKey;
        firstBinding = false;
      } else {
        isVar = this.peekKeywordLet();
        if (isVar) this.advance();
        rawKey = this.expectTemplateBindingKey();
        key = isVar ? rawKey : tplKey + rawKey[0].toUpperCase() + rawKey.substring(1);
        this.optionalCharacter(chars.$COLON);
      }

      let name: string = null !;
      let expression: ASTWithSource|null = null;
      if (isVar) {
        if (this.optionalOperator('=')) {
          name = this.expectTemplateBindingKey();
        } else {
          name = '\$implicit';
        }
      } else if (this.peekKeywordAs()) {
        this.advance();  // consume `as`
        name = rawKey;
        key = this.expectTemplateBindingKey();  // read local var name
        isVar = true;
      } else if (this.next !== EOF && !this.peekKeywordLet()) {
        const start = this.inputIndex;
        const ast = this.parsePipe();
        const source = this.input.substring(start - this.offset, this.inputIndex - this.offset);
        expression = new ASTWithSource(ast, source, this.location, this.errors);
      }

      bindings.push(new TemplateBinding(this.span(start), key, isVar, name, expression));
      if (this.peekKeywordAs() && !isVar) {
        const letStart = this.inputIndex;
        this.advance();                                   // consume `as`
        const letName = this.expectTemplateBindingKey();  // read local var name
        bindings.push(new TemplateBinding(this.span(letStart), letName, true, key, null !));
      }
      if (!this.optionalCharacter(chars.$SEMICOLON)) {
        this.optionalCharacter(chars.$COMMA);
      }
    } while (this.index < this.tokens.length);

    return new TemplateBindingParseResult(bindings, warnings, this.errors);
}

上面的代码描述了如何解析结构指令的算法。