详解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 相关文章推荐
JQuery调webservice实现邮箱验证(检测是否可用)
May 21 Javascript
JS合并数组的几种方法及优劣比较
Sep 19 Javascript
JavaScript移除数组内重复元素的方法
Mar 18 Javascript
BootStrap与validator 使用笔记(JAVA SpringMVC实现)
Sep 21 Javascript
JS实现探测网站链接的方法【测试可用】
Nov 08 Javascript
关于jQuery.ajax()的jsonp碰上post详解
Jul 02 jQuery
微信小程序中button组件的边框设置的实例详解
Sep 27 Javascript
angular的输入和输出的使用方法
Sep 22 Javascript
解决 viewer.js 动态更新图片导致无法预览的问题
May 14 Javascript
微信小程序实现手势滑动效果
Aug 26 Javascript
jQuery编写QQ简易聊天框
Aug 27 jQuery
node使用async_hooks模块进行请求追踪
Jan 28 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
关于PHP中的Class的几点个人看法
2006/10/09 PHP
php强制更新图片缓存的方法
2015/02/11 PHP
PHP图像裁剪缩略裁切类源码及使用方法
2016/01/07 PHP
php $_SESSION会员登录实例分享
2021/01/19 PHP
Laravel框架实现修改登录和注册接口数据返回格式的方法
2018/08/17 PHP
php 命名空间(namespace)原理与用法实例小结
2019/11/13 PHP
关闭页面window.location事件未执行的原因及解决方法
2014/09/01 Javascript
js事件监听器用法实例详解
2015/06/01 Javascript
C#中使用迭代器处理等待任务
2015/07/13 Javascript
jQuery实现简单下拉导航效果
2015/09/07 Javascript
JavaScript sort数组排序方法和自我实现排序方法小结
2016/06/06 Javascript
AngularJS变量及过滤器Filter用法分析
2016/11/22 Javascript
Bootstrap源码解读排版(1)
2016/12/23 Javascript
bootstrap PrintThis打印插件使用详解
2017/02/20 Javascript
基于Bootstrap框架实现图片切换
2017/03/10 Javascript
利用Console来Debug的10个高级技巧汇总
2018/03/26 Javascript
如何去除富文本中的html标签及vue、react、微信小程序中的过滤器
2018/11/21 Javascript
2020京东618叠蛋糕js脚本(亲测好用)
2020/06/02 Javascript
vue 虚拟DOM的原理
2020/10/03 Javascript
Python程序员开发中常犯的10个错误
2014/07/07 Python
Python的装饰器模式与面向切面编程详解
2015/06/21 Python
Python cookbook(数据结构与算法)从序列中移除重复项且保持元素间顺序不变的方法
2018/03/13 Python
在VS Code上搭建Python开发环境的方法
2018/04/06 Python
详解将Python程序(.py)转换为Windows可执行文件(.exe)
2019/07/19 Python
python threading和multiprocessing模块基本用法实例分析
2019/07/25 Python
Flask中endpoint的理解(小结)
2019/12/11 Python
tensorflow 获取所有variable或tensor的name示例
2020/01/04 Python
基于打开pycharm有带图片md文件卡死问题的解决
2020/04/24 Python
Python3 pyecharts生成Html文件柱状图及折线图代码实例
2020/09/29 Python
移动端Web页面的CSS3 flex布局快速上手指南
2016/05/31 HTML / CSS
销售活动策划方案
2014/08/26 职场文书
领导干部作风建设自查报告
2014/10/23 职场文书
教师党员个人总结
2015/02/10 职场文书
python爬取某网站原图作为壁纸
2021/06/02 Python
Java实现斗地主之洗牌发牌
2021/06/14 Java/Android
Go语言基础切片的创建及初始化示例详解
2021/11/17 Golang