Angular 2.x学习教程之结构指令详解


Posted in Javascript onMay 25, 2017

结构指令是什么

结构指令通过添加和删除 DOM 元素来更改 DOM 布局。Angular 中两个常见的结构指令是 *ngIf*ngFor

了解 * 号语法

* 号是语法糖,用于避免使用复杂的语法。我们以 *ngIf 指令为例:

Angular 2.x学习教程之结构指令详解

(图片来源:https://netbasal.com/)

  • Angular 把 host (宿主元素) 包装在 template 标签里面
  • Angular 将 ngIf 转换为属性绑定 - [ngIf]

创建结构指令

首先,让我们了解如何创建一个结构指令。 接下来我们将要实现一个简单的 ngIf 指令。

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({ selector: '[myNgIf]'})
export class MyNgIfDirective {

 constructor(
 private templateRef: TemplateRef<any>,
 private viewContainer: ViewContainerRef) { }

 @Input() set myNgIf(condition: boolean) {
 if (condition) {
  this.viewContainer.createEmbeddedView(this.templateRef);
 } else {
  this.viewContainer.clear();
 }
 }
}

我们可以按照以下方式使用我们的指令:

<div *myNgIf=”condition”></div>

下面我们来解释一下上面的代码。

TemplateRef

如名字所示,TemplateRef 用于表示模板的引用。

Angular 2.x学习教程之结构指令详解

(图片来源:https://netbasal.com/)

ViewContainerRef

正如上面介绍的,模板中包含了 DOM 元素,但如果要显示模板中定义的元素,我们就需要定义一个插入模板中元素的地方。在 Angular 中,这个地方被称作容器,而 ViewContainerRef 用于表示容器的引用。那什么元素会作为容器呢?

Angular 将使用 comment 元素替换 template 元素,作为视图容器。

我们来看一个具体的示例:

@Component({
 selector: 'my-app',
 template: `
 <div>
  <h2 *myNgIf="condition">Hello {{name}}</h2>
  <button (click)="condition = !condition">Click</button>
 </div>
 `,
})
export class App {
 name: string;
 condition: boolean = false;
 constructor() {
 this.name = 'Angular2'
 }
}

以上代码成功运行后,浏览器的显示内容如下:

Angular 2.x学习教程之结构指令详解

(图片来源:https://netbasal.com/)

ViewContainerRef 对象提供了 createEmbeddedView() 方法,该方法接收 TemplateRef 对象作为参数,并将模板中的内容作为容器 (comment 元素) 的兄弟元素,插入到页面中。

现在,你已经了解如何创建结构指令,接下来让我们看看两个具体的实例。

基于用户角色显示不同的内容

指令定义

@Directive({selector: '[ifRole]'})
export class IfRoleDirective {
 user$ : Subscription;
 @Input("ifRole") roleName : string;

 constructor(
  private templateRef : TemplateRef<any>,
  private viewContainer : ViewContainerRef,
  private authService : AuthService ) {}

 ngOnInit() {
 this.user$ = this.authService.user
  .do(() => this.viewContainer.clear())
  .filter(user => user.role === this.roleName)
  .subscribe(() => {
  this.viewContainer.createEmbeddedView(this.templateRef);
  });
 }

 ngOnDestroy() {
 this.user$.unsubscribe();
 }
}

指令应用

<div *ifRole="'admin'">
 Only for Admin
</div>

<div *ifRole="'client'">
 Only for Client
</div>

<div *ifRole="'editor'">
 Only for Editor
</div>

创建 Range 指令

指令定义

import { Directive, Input, ViewContainerRef, TemplateRef } from '@angular/core';

@Directive({
 selector: '[range]'
})
export class RangeDirective {
 _range: number[];

 @Input()
 set range(value: number) {
  this.vcr.clear();
  this._range = this.generateRange(value[0], value[1]);
  this._range.forEach(num => {
   this.vcr.createEmbeddedView(this.tpl, {
    $implicit: num
   });
  });
 }

 constructor(
  private vcr: ViewContainerRef,
  private tpl: TemplateRef<any>) { }

 private generateRange(from: number, to: number): number[] {
  var numbers: number[] = [];
  for (let i = from; i <= to; i++) {
   numbers.push(i);
  }
  return numbers;
 }
}

以上示例中,我们在调用 createEmbeddedView() 方法时,设置了第二个参数 {$implicit: num}  。Angular 为我们提供了 let 模板语法,允许在生成上下文时定义和传递上下文。

这将允许我们引用 *range="[20,30]; let num" 模板中声明的变量。我们使用 $implicit 名称,因为我们不知道用户在使用这个指令时,会使用什么名字。

Angular 2.x学习教程之结构指令详解

(图片来源:https://netbasal.com/)

指令应用

<h1>Your age:</h1>
<select>
 <ng-container *range="[18, 80]; let num">
 <option [ngValue]="num">{{num}}</option>
 </ng-container>
</select>

<h1>Year:</h1>
<select>
 <ng-container *range="[1998, 2016]; let num">
 <option [ngValue]="num">{{num}}</option>
 </ng-container>
</select>

以上代码成功运行后,浏览器的显示内容如下:

Angular 2.x学习教程之结构指令详解

(图片来源:https://netbasal.com/)

总结

以上就是这篇文章的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
jquery ready函数源代码研究
Dec 06 Javascript
javascript下string.format函数补充
Aug 24 Javascript
js实现可得到不同颜色值的颜色选择器实例
Feb 28 Javascript
JavaScript数组去重的3种方法和代码实例
Jul 01 Javascript
javascript每日必学之封装
Feb 23 Javascript
JavaScript中利用for循环遍历数组
Jan 15 Javascript
JavaScript canvas实现围绕旋转动画
Nov 18 Javascript
对angular 实时更新模板视图的方法$apply详解
Oct 09 Javascript
JavaScript封闭函数及常用内置对象示例
May 13 Javascript
JS阻止事件冒泡的方法详解
Aug 26 Javascript
TensorFlow.js 微信小程序插件开始支持模型缓存的方法
Feb 21 Javascript
TypeScript 使用 Tuple Union 声明函数重载
Apr 07 Javascript
bootstrap动态添加面包屑(breadcrumb)及其响应事件的方法
May 25 #Javascript
js获取一组日期中最近连续的天数
May 25 #Javascript
AngularJs定时器$interval 和 $timeout详解
May 25 #Javascript
slideToggle+slideup实现手机端折叠菜单效果
May 25 #Javascript
Bootstrap实现的标签页内容切换显示效果示例
May 25 #Javascript
React-router中结合webpack实现按需加载实例
May 25 #Javascript
node.js操作mongodb简单示例分享
May 25 #Javascript
You might like
php 页面执行时间计算代码
2008/12/04 PHP
一步一步学习PHP(7) php 字符串相关应用
2010/03/05 PHP
PHP函数篇之掌握ord()与chr()函数应用
2011/12/05 PHP
淘宝ip地址查询类分享(利用淘宝ip库)
2014/01/07 PHP
PHP面向对象程序设计之接口用法
2014/08/20 PHP
php实现无限级分类(递归方法)
2015/08/06 PHP
用php定义一个数组最简单的方法
2019/10/04 PHP
基于PHP+mysql实现新闻发布系统的开发
2020/08/06 PHP
Jquery post传递数组方法实现思路及代码
2013/04/28 Javascript
iframe子页面获取父页面元素的方法
2013/11/05 Javascript
jquery append()方法与html()方法的区别及使用介绍
2014/08/01 Javascript
怎么通过onclick事件获取js函数返回值(代码少)
2015/07/28 Javascript
javascript实现label标签跳出循环操作
2016/03/06 Javascript
jQuery原理系列-css选择器的简单实现
2016/06/07 Javascript
ReactJs快速入门教程(精华版)
2016/11/28 Javascript
JavaScript函数式编程(Functional Programming)纯函数用法分析
2019/05/22 Javascript
JavaScript中的函数申明、函数表达式、箭头函数
2019/12/06 Javascript
JavaScript find()方法及返回数据实例
2020/04/30 Javascript
vc6编写python扩展的方法分享
2014/01/17 Python
在Python中使用成员运算符的示例
2015/05/13 Python
Python基于pyCUDA实现GPU加速并行计算功能入门教程
2018/06/19 Python
Python多线程实现支付模拟请求过程解析
2020/04/21 Python
python实现音乐播放和下载小程序功能
2020/04/26 Python
html5使用canvas绘制一张图片
2014/12/15 HTML / CSS
html5默认气泡修改的代码详解
2020/03/13 HTML / CSS
乌克兰香水和化妆品网站:Notino.ua
2018/03/26 全球购物
实习生自荐信范文
2013/11/13 职场文书
个人实用的自我评价范文
2013/11/23 职场文书
小学生评语大全
2014/04/18 职场文书
本科毕业论文导师评语
2014/12/31 职场文书
高中运动会前导词
2015/07/20 职场文书
导游词之澳门妈祖庙
2019/12/19 职场文书
使用pycharm运行flask应用程序的详细教程
2021/06/07 Python
JS 基本概念详细介绍
2021/10/16 Javascript
Python帮你解决手机qq微信内存占用太多问题
2022/02/15 Python
电脑开机弹出documents文件夹怎么回事?弹出documents文件夹解决方法
2022/04/08 数码科技