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 缩图函数 (onDOMLoaded)……
Oct 23 Javascript
使用JavaScript链式编程实现模拟Jquery函数
Dec 21 Javascript
JavaScript+CSS实现的可折叠二级菜单实例
Feb 29 Javascript
Node.js的文件权限及读写flag详解
Oct 11 Javascript
JS实现颜色动态淡化效果
Mar 06 Javascript
微信小程序用户自定义模版用法实例分析
Nov 28 Javascript
JS中的BOM应用
Feb 02 Javascript
vue自定义tap指令及tap事件的实现
Sep 18 Javascript
VUE2.0+ElementUI2.0表格el-table循环动态列渲染的写法详解
Nov 30 Javascript
js console.log打印对象时属性缺失的解决方法
May 23 Javascript
vue内置组件component--通过is属性动态渲染组件操作
Jul 28 Javascript
JS实现鼠标移动拖尾
Dec 27 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计算数组不为空元素个数的方法
2014/01/27 PHP
PHP给文字内容中的关键字进行套红处理
2016/04/12 PHP
thinkphp5.1 框架钩子和行为用法实例分析
2020/05/25 PHP
CSS常用网站布局实例
2008/04/03 Javascript
JavaScript中也使用$美元符号来代替document.getElementById
2010/06/19 Javascript
最佳JS代码编写的14条技巧
2011/01/09 Javascript
jQuery选择器中含有空格的使用示例及注意事项
2013/08/25 Javascript
js中settimeout方法加参数的使用实例
2014/02/27 Javascript
javascript简单实现类似QQ头像弹出效果的方法
2015/08/03 Javascript
BootStrap树状图显示功能
2016/11/24 Javascript
JS中用try catch对代码运行的性能影响分析
2016/12/26 Javascript
ztree简介_动力节点Java学院整理
2017/07/19 Javascript
纯javascript前端实现base64图片下载(兼容IE10+)
2018/09/14 Javascript
详解关于React-Router4.0跳转不置顶解决方案
2019/05/10 Javascript
小程序调用微信支付的方法
2019/09/26 Javascript
详解三种方式在React中解决绑定this的作用域问题并传参
2020/08/18 Javascript
[15:39]教你分分钟做大人:龙骑士
2014/10/30 DOTA
[04:12]第二届DOTA2亚洲邀请赛选手传记-Newbee.Sccc
2017/04/03 DOTA
[52:36]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
详解python如何调用C/C++底层库与互相传值
2016/08/10 Python
python 字符串转列表 list 出现\ufeff的解决方法
2017/06/22 Python
scrapy框架携带cookie访问淘宝购物车功能的实现代码
2020/07/07 Python
CSS3 实现童年的纸飞机
2019/05/05 HTML / CSS
潘多拉意大利官方网上商城:网上选购PANDORA珠宝
2018/10/07 全球购物
澳大利亚在线购买葡萄酒:The Wine Collective
2020/02/20 全球购物
Napapijri西班牙在线商店:夹克、外套、运动衫等
2020/11/05 全球购物
4s店销售经理岗位职责
2014/07/19 职场文书
反对四风自我剖析材料
2014/10/07 职场文书
司法局群众路线教育实践活动整改措施思想汇报
2014/10/13 职场文书
工作时间擅自离岗检讨书
2014/10/24 职场文书
2015年医院创卫工作总结
2015/04/22 职场文书
2015年政协委员工作总结
2015/05/20 职场文书
2015年工会工作总结范文
2015/07/23 职场文书
婚礼领导致辞大全
2015/07/28 职场文书
少年的你:世界上没有如果,要在第一次就勇敢的反抗
2019/11/20 职场文书
《正面管教》读后有感:和善而坚定的旅程
2019/12/19 职场文书