Angular 自定义结构指令

作者: Keriy | 来源:发表于2017-06-21 00:43 被阅读0次

1. <ng-template>元素

import { Component, TemplateRef, ViewContainerRef, ViewChild,
  AfterViewInit } from '@angular/core';
@Component({
  selector: 'app-code404',
  template: `
  <!-- 这里使用一个模板变量,在组件中使用@ViewChild装饰器获取模板元素-->
    <ng-template #tpl>
      Big Keriy !
    </ng-template>
  `,
})
export class Code404Component implements AfterViewInit{

  // @ViewChild 装饰器获取模板元素
  @ViewChild('tpl')
  tplRef: TemplateRef<any>;
  constructor(private vcRef: ViewContainerRef) {}
  ngAfterViewInit() {
    
    // 使用ViewContainerRef对象的createEmbeddedView方法创建内嵌视图。
    this.vcRef.createEmbeddedView(this.tplRef);
  } }

这样其实我们在视图中就得到了一个什么...啊,就是一个'Big Keriy !'的字符串。

2. ngTemplateOutlet指令

a. ngTemplateOutlet
routerOutlet是一个意思,将视图(<ng-template>标签中的内容)放到对应的ngTemplateoutlet下面。

import { Component } from '@angular/core';
  @Component({
    selector: 'app-code404',
    template: `
      <ng-template #stpl>
        Hello, Semlinker!
      </ng-template>
      <ng-template #atpl>
        Big Keriy !
      </ng-template>
      <div [ngTemplateOutlet]="atpl"></div>
      <div [ngTemplateOutlet]="stpl"></div>
`, })
  export class Code404Component { }

最终的视图应该是:

Big Keriy !
Hello, Semlinker!

b. ngOutletContex
看名字就知道意思。
ngTemplateOutlet指令基于TemplateRef对象,在使用ngTemplateOutlet指令时,可以通过ngTemplateOutletContext属性来设置来设置EmbeddedViewRef上下文对象。可以使用let语法来声明绑定上下文对象属性名。

import { Component, TemplateRef, ViewContainerRef, ViewChild,
  AfterViewInit } from '@angular/core';
@Component({
  selector: 'app-code404',
  template: `
    <!-- 这里的messagey映射到下面context中message 再使用插值表达式的方式显示message的值 -->
    <ng-template #stpl let-message="message">
      <p>{{message}}</p>
    </ng-template>
    <!-- 这里的messagey映射到下面context中message , let-msg是一种与语法糖的方式变量名是msg-->
    <ng-template #atpl let-msg="message">
      <p>{{msg}}</p>
    </ng-template>
    <!-- 若不指定变量值那么将显示 $implicit 的值-->
    <ng-template #otpl let-msg>
      <p>{{msg}}</p>
    </ng-template>
    <div [ngTemplateOutlet]="atpl"
          // 这里ngOutletContext绑定的是context对象
         [ngOutletContext]="context">
    </div>
    <div [ngTemplateOutlet]="stpl"
         [ngOutletContext]="context">
    </div>
    <div [ngTemplateOutlet]="otpl"
         [ngOutletContext]="context">
    </div>
  `,
})
export class Code404Component implements AfterViewInit{
  @ViewChild('tpl')
  tplRef: TemplateRef<any>;
  constructor(private vcRef: ViewContainerRef) {}
  ngAfterViewInit() {
    this.vcRef.createEmbeddedView(this.tplRef);
  }
  context = { message: 'Hello ngOutletContext!',
    $implicit: 'great, Semlinker!' };
    // 这里的$implicit是固定写法
}

先看输出的视图:

Hello ngOutletContext!
Hello ngOutletContext!
Hello, Semlinker!

3. ngComponentOutlet指令

听着名字就很爽,这不是插入视图的,是插入组件的!

该指令使用声明的方式,动态加载组件。

先写组件,里面有两个。。组件:

  @Component({
    selector: 'alert-success',
    template: `
      <p>Alert success</p>
    `,
  })
  export class AlertSuccessComponent { }
  @Component({
    selector: 'alert-danger',
    template: `
      <p>Alert danger</p>
    `,
  })
  export class AlertDangerComponent { }
  @Component({
    selector: 'my-app',
    template: `
      <h1>Angular version 4</h1>
      <ng-container *ngComponentOutlet="alert"></ng-container>
      <button (click)="changeComponent()">Change component</button>
  `, })
  export class AppComponent {
     alert = AlertSuccessComponent;
    changeComponent() {
      this.alert = AlertDangerComponent;
  } 
}

当然,还需要在模块中声明入口:

// app.module.ts
@NgModule({
    // ...
    declarations: [
      AppComponent,
      SignUpComponent,
      AlertSuccessComponent,
      AlertDangerComponent
    ],
    entryComponents: [       // 这里面写指令中呀用到的组件
      AlertSuccessComponent,
      AlertDangerComponent
],
// ...
})

这样就可以使用ngComponentOutlet指令来插入组件玩耍了:

<!-- 简单语法 -->
<ng-container *ngComponentOutlet="componentTypeExpression"></ng-container>

<!-- 完整语法 -->
<ng-container *ngComponentOutlet="componentTypeExpression;
     injector: injectorExpression;
     content: contentNodesExpression;">
</ng-container>

这是一个完整语法简单的例子:

// ...
@Component({
  selector: 'ng-component-outlet-complete-example',
  template: `
    <ng-container *ngComponentOutlet="CompleteComponent; 
                                      injector: myInjector; 
                                      content: myContent"></ng-container>`
})
class NgTemplateOutletCompleteExample {
  // This field is necessary to expose CompleteComponent to the template.
  CompleteComponent = CompleteComponent;
  myInjector: Injector;
 
  myContent = [[document.createTextNode('Ahoj')], [document.createTextNode('Svet')]];
 
  constructor(injector: Injector) {
    this.myInjector = ReflectiveInjector.resolveAndCreate([Greeter], injector);
  }
}

4. 创建结构指令

也想不出来一个什么好例子,抄一个例子过来:

// uless.directive.ts

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
  @Directive({
      selector: '[exeUnless]'
  })
  export class UnlessDirective {
      @Input('exeUnless')
      set condition(newCondition: boolean) {  // set condition
          if (!newCondition) {
              this.viewContainer.createEmbeddedView(this.templateRef);
          } else {
              this.viewContainer.clear();
          } 
      }
      constructor(private templateRef: TemplateRef<any>,
          private viewContainer: ViewContainerRef) {
      } 
  }


  import { Component } from '@angular/core';
  @Component({
    selector: 'app-root',
    template: `
     <h2 *exeUnless="condition">Hello, Semlinker!</h2>
    `,
  })
  export class AppComponent {
    condition: boolean = false;
  }
  
  
  // app.component.ts
  
  import { Component } from '@angular/core';
  @Component({
    selector: 'app-root',
    template: `
     <h2 *exeUnless="condition">Hello, Semlinker!</h2>
    `,
  })
  export class AppComponent {
    condition: boolean = false;
  }

本文部分摘自SemlinkerAngular 4 指令快速入门,感谢作者的分享。

相关文章

网友评论

    本文标题:Angular 自定义结构指令

    本文链接:https://www.haomeiwen.com/subject/hrqzqxtx.html