Angular2:ngfor如何扩展

时间:2016-08-03 20:09:45

标签: angular angular2-template

我知道<div *ngFor="let foo of foobars">{{foo.stuff}}</div>上的教科书规则变为<template ngFor let-foo="$implicit" [ngForOf]="foobars"><div>...</div></template>。我的问题有两方面:

  • 如何吗
  • 我自己需要做些什么才能利用这种机制(&#34; microsyntax&#34;)?

即将<div *myDirective="item">{{item.stuff}}</div>转变为<template myDirective let-item="$implicit"><div>{{item.stuff}}</div></template>

由于我从上到下阅读了ngFor的源代码,我只能假设这个黑魔法在编译器的某个地方,我已经在角度github上下,但我不能把手指放在上面。 帮助!

2 个答案:

答案 0 :(得分:13)

是的,所有的魔法都发生在编译器中。

让我们来看看这个模板:

<div *ngFor="let foo of foobars">{{foo}}</div>

首先它将转换为以下内容:

<div template="ngFor let foo of foobars>{{foo}}</div>

然后:

<template ngFor let-foo [ngForOf]="foobars"><div>{{foo}}</div></template>

在Angular2 rc.4中,它看起来像这样 enter image description here

首先生成ast树节点(抽象语法树节点)然后所有魔法发生在TemplateParseVisitor.visitElementhttps://github.com/angular/angular/blob/2.0.0-rc.4/modules/%40angular/compiler/src/template_parser.ts#L284)特别是底部(https://github.com/angular/angular/blob/2.0.0-rc.4/modules/%40angular/compiler/src/template_parser.ts#L394

if (hasInlineTemplates) {
  var templateCssSelector = createElementCssSelector(TEMPLATE_ELEMENT, templateMatchableAttrs);
  var templateDirectiveMetas = this._parseDirectives(this.selectorMatcher, templateCssSelector);
  var templateDirectiveAsts = this._createDirectiveAsts(
      true, element.name, templateDirectiveMetas, templateElementOrDirectiveProps, [],
      element.sourceSpan, []);
  var templateElementProps: BoundElementPropertyAst[] = this._createElementPropertyAsts(
      element.name, templateElementOrDirectiveProps, templateDirectiveAsts);
  this._assertNoComponentsNorElementBindingsOnTemplate(
      templateDirectiveAsts, templateElementProps, element.sourceSpan);
  var templateProviderContext = new ProviderElementContext(
      this.providerViewContext, parent.providerContext, parent.isTemplateElement,
      templateDirectiveAsts, [], [], element.sourceSpan);
  templateProviderContext.afterElement();

  parsedElement = new EmbeddedTemplateAst(
      [], [], [], templateElementVars, templateProviderContext.transformedDirectiveAsts,
      templateProviderContext.transformProviders,
      templateProviderContext.transformedHasViewContainer, [parsedElement], ngContentIndex,
      element.sourceSpan);
}
return parsedElement;

此方法返回EmbeddedTemplateAst。它与:

相同
<template ngFor let-foo [ngForOf]="foobars"><div>{{foo}}</div></template>

如果你想转:

<div *myDirective="item">{{item.stuff}}</div>

<template myDirective let-item><div>{{item.stuff}}</div></template>

然后您需要使用以下语法:

<div *myDirective="let item">{{item.stuff}}</div>

但在这种情况下,你不会传递上下文。 您的自定义结构指令可能如下所示:

@Directive({
  selector: '[myDirective]'
})
export class MyDirective {
  constructor(
    private _viewContainer: ViewContainerRef, 
    private _templateRef: TemplateRef<any>) {}

   @Input() set myDirective(prop: Object) {
    this._viewContainer.clear();
    this._viewContainer.createEmbeddedView(this._templateRef, prop); <== pass context
  }
} 

您可以像以下一样使用它:

<div *myDirective="item">{{item.stuff}}</div>

               ||
               \/

<div template="myDirective:item">{{item.stuff}}</div>

               ||
               \/

<template [myDirective]="item">
   <div>{{item.stuff}}</div>
</template>

我希望这有助于您了解结构指令的工作原理。

<强>更新

让我们看看它是如何运作的( plunker

*dir="let foo v foobars" => [dirV]="foobars"

enter image description here

所以你可以编写以下指令:

@Directive({
  selector: '[dir]'
})
export class MyDirective {
  @Input()
  dirV: any;

  @Input()
  dirK: any;

  ngAfterViewInit() {
    console.log(this.dirV, this.dirK);
  }
}

@Component({
  selector: 'my-app',
  template: `<h1>Angular 2 Systemjs start</h1>
  <div *dir="let foo v foobars k arr">{ foo }</div>
  `,
  directives: [MyDirective]
})
export class AppComponent {
  foobars = [1, 2, 3];
  arr = [3,4,5]
}

以下是相应的 Plunker

另见

您可以在此处找到实时示例https://alexzuza.github.io/enjoy-ng-parser/

答案 1 :(得分:0)

UILocalNotification *localNotification = [[UILocalNotification alloc] init]; localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:10]; localNotification.alertTitle = @"Welcome"; localNotification.alertBody = @"Thank You for installing Application"; localNotification.soundName = UILocalNotificationDefaultSoundName; localNotification.timeZone = [NSTimeZone defaultTimeZone]; [[UIApplication sharedApplication] scheduleLocalNotification:localNotification]; *ngFor,...是结构指令。

将其应用于*ngIf元素,或以<template>

作为前缀

https://angular.io/docs/ts/latest/guide/structural-directives.html#!#unless

*