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