详解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 相关文章推荐
js+FSO遍历文件夹下文件并显示
Mar 07 Javascript
纯js分页代码(简洁实用)
Nov 05 Javascript
AngularJS控制器之间的数据共享及通信详解
Aug 01 Javascript
mvc中form表单提交的三种方式(推荐)
Aug 10 Javascript
基于VUE选择上传图片并页面显示(图片可删除)
May 25 Javascript
基于JavaScript实现百度搜索框效果
Jun 28 Javascript
vue中使用ueditor富文本编辑器
Feb 08 Javascript
小程序实现投票进度条
Nov 20 Javascript
vue页面更新patch的实现示例
Mar 25 Javascript
Vue实现图片轮播组件思路及实例解析
May 11 Javascript
jQuery带控制按钮轮播图插件
Jul 31 jQuery
vue将data恢复到初始状态 &amp;&amp; 重新渲染组件实例
Sep 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
解析php开发中的中文编码问题
2013/08/08 PHP
PHP使用PHPexcel导入导出数据的方法
2015/11/14 PHP
分享PHP守护进程类
2015/12/30 PHP
Laravel5框架添加自定义辅助函数的方法
2018/08/01 PHP
ASP.NET中基于JQUERY的高性能的TreeView补充
2011/02/23 Javascript
javascript获取xml节点的最大值(实现代码)
2013/12/11 Javascript
jquery操作cookie插件分享
2014/01/14 Javascript
javascript event在FF和IE的兼容传参心得(绝对好用)
2014/07/10 Javascript
前端学习笔记style,currentStyle,getComputedStyle的用法与区别
2016/05/28 Javascript
nodejs开发——express路由与中间件
2017/03/24 NodeJs
关于redux-saga中take使用方法详解
2018/02/27 Javascript
vue自定义指令实现方法详解
2019/02/11 Javascript
详解element上传组件before-remove钩子问题解决
2020/04/08 Javascript
详解webpack的文件监听实现(热更新)
2020/09/11 Javascript
基于JavaScript实现随机点名器
2021/02/25 Javascript
[02:51]DOTA2英雄基础教程 艾欧
2014/01/13 DOTA
使用PYTHON接收多播数据的代码
2012/03/01 Python
python 字典(dict)遍历的四种方法性能测试报告
2014/06/25 Python
python中的多线程实例教程
2014/08/27 Python
python 回调函数和回调方法的实现分析
2016/03/23 Python
详解python eval函数的妙用
2017/11/16 Python
用Python写王者荣耀刷金币脚本
2017/12/21 Python
Python学习笔记之open()函数打开文件路径报错问题
2018/04/28 Python
python批量导入数据进Elasticsearch的实例
2018/05/30 Python
对PyTorch torch.stack的实例讲解
2018/07/30 Python
TensorFlow实现指数衰减学习率的方法
2020/02/05 Python
python 中的[:-1]和[::-1]的具体使用
2020/02/13 Python
带你学习Python如何实现回归树模型
2020/07/16 Python
使用CSS3的rem属性制作响应式页面布局的要点解析
2016/05/24 HTML / CSS
办公室驾驶员岗位职责
2013/11/15 职场文书
培训演讲稿范文
2014/01/12 职场文书
国培远程培训感言
2014/03/08 职场文书
迎国庆演讲稿
2014/09/15 职场文书
高校教师个人总结
2015/02/10 职场文书
HTML+CSS 实现顶部导航栏菜单制作
2021/06/03 HTML / CSS
「月刊Action」2022年5月号封面公开
2022/03/21 日漫