欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解Angular 自定义结构指令

程序员文章站 2022-06-24 17:03:01
1. 元素 import { component, templateref, viewcontainerref, viewc...

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;
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。