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 相关文章推荐
javascript学习笔记(十二) RegExp类型介绍
Jun 20 Javascript
js确认框confirm()用法实例详解
Jan 07 Javascript
AngularJS全局scope与Isolate scope通信用法示例
Nov 22 Javascript
Angular.js中处理页面闪烁的方法详解
Mar 09 Javascript
JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题
Jun 30 Javascript
js获取元素的偏移量offset简单方法(必看)
Jul 05 Javascript
浅谈JsonObject中的key-value数据解析排序问题
Dec 06 Javascript
javaScript手机号码校验工具类PhoneUtils详解
Dec 08 Javascript
小程序如何使用分包加载的实现方法
May 22 Javascript
js实现盒子滚动动画效果
Aug 09 Javascript
js中实现继承的五种方法
Jan 25 Javascript
利用 Chrome Dev Tools 进行页面性能分析的步骤说明(前端性能优化)
Feb 24 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
德生H-501的评价与改造
2021/03/02 无线电
PR值查询 | PageRank 查询
2006/12/20 PHP
深入理解PHP原理之错误抑制与内嵌HTML分析
2011/05/02 PHP
小谈php正则提取图片地址
2014/03/27 PHP
js与jquery实时监听输入框值的oninput与onpropertychange方法
2015/02/05 Javascript
javascript实现带下拉子菜单的导航菜单效果
2015/05/14 Javascript
javascript匀速运动实现方法分析
2016/01/08 Javascript
属于你的jQuery提示框(Tip)插件
2016/01/20 Javascript
javascript实现粘贴qq截图功能(clipboardData)
2016/05/29 Javascript
node.js路径处理方法以及绝对路径详解
2021/03/04 Javascript
jQuery插件FusionCharts实现的Marimekko图效果示例【附demo源码】
2017/03/24 jQuery
bootstrap fileinput组件整合Springmvc上传图片到本地磁盘
2017/05/11 Javascript
原生JavaScrpit中异步请求Ajax实现方法
2017/11/03 Javascript
微信小程序版本自动更新的方法
2019/06/14 Javascript
VueJS 取得 URL 参数值的方法
2019/07/19 Javascript
vue+elementUi图片上传组件使用详解
2019/08/20 Javascript
JavaScript 中的执行上下文和执行栈实例讲解
2021/02/25 Javascript
[05:05]第三天的dota2
2013/07/29 DOTA
用Python代码来解图片迷宫的方法整理
2015/04/02 Python
Python中的Matplotlib模块入门教程
2015/04/15 Python
Python中urllib+urllib2+cookielib模块编写爬虫实战
2016/01/20 Python
python 中的int()函数怎么用
2017/10/17 Python
pyqt5自定义信号实例解析
2018/01/31 Python
用tensorflow搭建CNN的方法
2018/03/05 Python
python微元法计算函数曲线长度的方法
2018/11/08 Python
python利用Opencv实现人脸识别功能
2019/04/25 Python
Python使用微信接入图灵机器人过程解析
2019/11/04 Python
在Python中利用pickle保存变量的实例
2019/12/30 Python
使用Numpy对特征中的异常值进行替换及条件替换方式
2020/06/08 Python
岗位职责范本
2013/11/23 职场文书
学院书画协会部门岗位职责
2013/12/01 职场文书
房地产销售经理岗位职责
2014/01/01 职场文书
影视广告专业求职信
2014/09/02 职场文书
2015年幼儿园保育工作总结
2015/05/12 职场文书
中考百日冲刺决心书
2015/09/22 职场文书
2016春季小学开学寄语
2015/12/03 职场文书