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 相关文章推荐
新闻内页-JS分页
Jun 07 Javascript
从父页面读取和操作iframe中内容方法
Jul 25 Javascript
JavaScript 页面编码与浏览器类型判断代码
Jun 03 Javascript
jQuery不使用插件及swf实现无刷新文件上传
Dec 08 Javascript
基于AngularJS实现页面滚动到底自动加载数据的功能
Oct 16 Javascript
H5移动端适配 Flexible方案
Oct 24 Javascript
jQuery选择器特殊字符与属性空格问题
Aug 14 jQuery
使用Vue-cli 3.0搭建Vue项目的方法
Jun 07 Javascript
vue2.0项目集成Cesium的实现方法
Jul 30 Javascript
vue中组件通信详解(父子组件, 爷孙组件, 兄弟组件)
Jul 27 Javascript
Vue循环中多个input绑定指定v-model实例
Aug 31 Javascript
如何利用JS将手机号中间四位变成*号
Sep 29 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安装全攻略:APACHE
2006/10/09 PHP
浅谈web上存漏洞及原理分析、防范方法(文件名检测漏洞)
2013/06/29 PHP
配置php.ini实现PHP文件上传功能
2014/11/27 PHP
PHP5多态性与动态绑定介绍
2015/04/03 PHP
将HTML自动转为JS代码
2006/06/26 Javascript
JavaScript Event学习第六章 事件的访问
2010/02/07 Javascript
JavaScript的类型简单说明
2010/09/03 Javascript
FireFox下XML对象转化成字符串的解决方法
2011/12/09 Javascript
jQuery获得页面元素的绝对/相对位置即绝对X,Y坐标
2014/03/06 Javascript
基于jQuery实现动态搜索显示功能
2016/05/05 Javascript
jQuery+PHP实现微信转盘抽奖功能的方法
2016/05/25 Javascript
KnockoutJS 3.X API 第四章之表单textInput、hasFocus、checked绑定
2016/10/11 Javascript
jQuery居中元素scrollleft计算方法示例
2017/01/16 Javascript
JavaScript运动框架 多物体任意值运动(三)
2017/05/17 Javascript
通过构造函数实例化对象的方法
2017/06/28 Javascript
vue axios 二次封装的示例代码
2017/12/08 Javascript
微信小程序使用template标签实现五星评分功能
2018/11/03 Javascript
python中私有函数调用方法解密
2016/04/29 Python
python中使用print输出中文的方法
2018/07/16 Python
在python中利用try..except来代替if..else的用法
2019/12/19 Python
Pytorch 多维数组运算过程的索引处理方式
2019/12/27 Python
解决Pytorch训练过程中loss不下降的问题
2020/01/02 Python
检测tensorflow是否使用gpu进行计算的方式
2020/02/03 Python
Python socket处理client连接过程解析
2020/03/18 Python
关于python 的legend图例,参数使用说明
2020/04/17 Python
python 对一幅灰度图像进行直方图均衡化
2020/10/27 Python
全球领先美式家具品牌:Ashley爱室丽家居
2017/08/07 全球购物
linux面试题参考答案(11)
2012/05/01 面试题
创新型城市实施方案
2014/03/06 职场文书
人口与计划生育目标管理责任书
2014/07/29 职场文书
重点工程汇报材料
2014/08/27 职场文书
学习走群众路线心得体会
2014/11/05 职场文书
承兑汇票转让证明怎么写?
2014/11/30 职场文书
如何使用Python提取Chrome浏览器保存的密码
2021/06/09 Python
nginx 配置指令之location使用详解
2022/05/25 Servers
不想升级Win11?教你彻底锁定老版Windows系统的方法(附下载地址)
2022/09/23 数码科技