发表于: 2017-06-21 22:31:02

2 933


今天完成的事情:

稍微深入学习Angular依赖注入,恩。


明天计划的事情:

依赖注入还有两节比较难的东西,明天看完。


遇到问题:

其实依赖注入是个很深的东西,了解的越多就越感觉什么都不会。一山更比一山高。


收获:

昨天写了自定义属性指令,今天写结构指令吧。



Angular 自定义结构指令

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 vcRefViewContainerRef) {}
 ngAfterViewInit() {
   
   // 使ViewContainerRefcreateEmbeddedView
   this.vcRef.createEmbeddedView(this.tplRef);
 } }

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

2. ngTemplateOutlet指令

ngTemplateOutlet
routerOutlet是一个意思,将视图(标签中的内容)放到对应的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!

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

import { Component, TemplateRef, ViewContainerRef, ViewChild,
 AfterViewInit } from '@angular/core';
@Component({
 selector: 'app-code404',
 template: `
   <!-- messageycontextmessage 使message -->
   <ng-template #stpl let-message="message">
     <p>{{message}}</p>
   </ng-template>
   <!-- messageycontextmessage , let-msgmsg-->
   <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"
         // ngOutletContextcontext
        [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 vcRefViewContainerRef) {}
 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;
 myInjectorInjector;
 myContent = [[document.createTextNode('Ahoj')], [document.createTextNode('Svet')]];
 constructor(injectorInjector) {
   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(newConditionboolean) {  // set condition
         if (!newCondition) {
             this.viewContainer.createEmbeddedView(this.templateRef);
         } else {
             this.viewContainer.clear();
         }
     }
     constructor(private templateRefTemplateRef<any>,
         private viewContainer: ViewContainerRef) {
     }
 }
 import { Component } from '@angular/core';
 @Component({
   selector: 'app-root',
   template: `
    <h2 *exeUnless="condition">Hello, Semlinker!</h2>
   `,
 })
 export class AppComponent {
   conditionboolean = false;
 }
 
 
 // app.component.ts
 
 import { Component } from '@angular/core';
 @Component({
   selector: 'app-root',
   template: `
    <h2 *exeUnless="condition">Hello, Semlinker!</h2>
   `,
 })
 export class AppComponent {
   conditionboolean = false;
 }



返回列表 返回列表
评论

    分享到