详解Angular 自定义结构指令


Posted in Javascript onJune 21, 2017

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

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

Javascript 相关文章推荐
点图片上一页下一页翻页效果
Jul 09 Javascript
JS获取整个页面文档的实现代码
Dec 15 Javascript
原生Js实现简易烟花爆炸效果的方法
Mar 20 Javascript
Angularjs实现多个页面共享数据的方式
Mar 29 Javascript
javascript高级选择器querySelector和querySelectorAll全面解析
Apr 07 Javascript
JavaScript中点击事件的写法
Jun 28 Javascript
web打印小结
Jan 11 Javascript
简单谈谈React中的路由系统
Jul 25 Javascript
JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例
Dec 14 Javascript
js实现拖拽与碰撞检测
Sep 18 Javascript
jQuery实现二级导航菜单的示例
Sep 30 jQuery
js实现复制粘贴的两种方法
Dec 04 Javascript
详解Angular2 之 结构型指令
Jun 21 #Javascript
JavaScript用200行代码制作打飞机小游戏实例
Jun 21 #Javascript
Angular.JS中指令ng-if的注意事项小结
Jun 21 #Javascript
jquery.validate表单验证插件使用详解
Jun 21 #jQuery
JS实现简单拖拽效果
Jun 21 #Javascript
详解Vue路由开启keep-alive时的注意点
Jun 20 #Javascript
jquery基于layui实现二级联动下拉选择(省份城市选择)
Jun 20 #jQuery
You might like
动态新闻发布的实现及其技巧
2006/10/09 PHP
php中apc缓存使用示例
2013/12/25 PHP
PHP实现的一致性哈希算法完整实例
2015/11/14 PHP
PHP Cookei记录用户历史浏览信息的代码
2016/02/03 PHP
php使用glob函数遍历文件和目录详解
2016/09/23 PHP
yii2实现分页,带搜索的分页功能示例
2017/01/07 PHP
如何利用预加载优化Laravel Model查询详解
2017/08/11 PHP
PHP对称加密算法(DES/AES)类的实现代码
2017/11/14 PHP
Javascript中的默认参数详解
2014/10/22 Javascript
coffeescript使用的方式汇总
2015/08/05 Javascript
json传值以及ajax接收详解
2016/05/24 Javascript
Highcharts学习之坐标轴
2016/08/02 Javascript
Three.js学习之Lamber材质和Phong材质
2016/08/04 Javascript
解析ajaxFileUpload 异步上传文件简单使用
2016/12/30 Javascript
vue 和vue-touch 实现移动端左右导航效果(仿京东移动站导航)
2017/04/22 Javascript
js实现省市级联效果分享
2017/08/10 Javascript
为什么使用koa2搭建微信第三方公众平台的原因
2018/05/16 Javascript
JS动态图片的实现方法完整示例
2020/01/13 Javascript
[04:56]经典回顾:前Ehome 与 前LGD
2015/02/26 DOTA
python自动化工具日志查询分析脚本代码实现
2013/11/26 Python
Python中让MySQL查询结果返回字典类型的方法
2014/08/22 Python
浅谈Pytorch torch.optim优化器个性化的使用
2020/02/20 Python
使用python-Jenkins批量创建及修改jobs操作
2020/05/12 Python
中东地区最大的奢侈品市场:The Luxury Closet
2019/04/09 全球购物
倩碧澳大利亚官网:Clinique澳大利亚
2019/07/22 全球购物
什么是触发器(trigger)? 触发器有什么作用?
2013/09/18 面试题
升职自荐信
2013/11/28 职场文书
小学教师听课制度
2014/02/01 职场文书
整顿机关作风心得体会
2014/09/10 职场文书
运动会加油稿100字
2014/09/19 职场文书
工作业绩不及格检讨书
2014/10/28 职场文书
兵马俑的导游词
2015/02/02 职场文书
2015年劳动部工作总结
2015/05/23 职场文书
植物园观后感
2015/06/11 职场文书
MySQL千万级数据表的优化实战记录
2021/08/04 MySQL
mysql 获取时间方式
2022/03/20 MySQL