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 相关文章推荐
prototype 源码中文说明之 prototype.js
Sep 22 Javascript
妙用Jquery的val()方法
Jun 27 Javascript
jQuery学习笔记之基础中的基础
Jan 19 Javascript
JavaScript组件焦点与页内锚点间传值的方法
Feb 02 Javascript
微信小程序链接传参并跳转新页面
Nov 29 Javascript
vue拦截器Vue.http.interceptors.push使用详解
Apr 22 Javascript
vue通过路由实现页面刷新的方法
Jan 25 Javascript
深入浅析AngularJs模版与v-bind
Jul 06 Javascript
Vue+webpack+Element 兼容问题总结(小结)
Aug 16 Javascript
详细教你微信公众号正文页SVG交互开发技巧
Jul 25 Javascript
小程序实现背景音乐播放和暂停
Jun 19 Javascript
解决vue项目中遇到 Cannot find module ‘chalk‘ 报错的问题
Nov 05 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 mb_convert_encoding 获取字符串编码类型实现代码
2009/04/26 PHP
一个PHP数组应该有多大的分析
2009/07/30 PHP
php for 循环语句使用方法详细说明
2010/05/09 PHP
php实现读取手机客户端浏览器的类
2015/01/09 PHP
CodeIgniter框架基本增删改查操作示例
2017/03/23 PHP
jQuery图片播放8款精美插件分享
2013/02/17 Javascript
表单类各种类型(文本框)失去焦点效果jquery代码
2013/04/26 Javascript
JS操作select下拉框动态变动(创建/删除/获取)
2013/06/02 Javascript
JS操作iframe里的dom(实例讲解)
2014/01/29 Javascript
javascript简单实现图片预加载
2014/12/03 Javascript
JavaScript中遍历对象的property的3种方法介绍
2014/12/30 Javascript
JS使用parseInt解析数字实现求和的方法
2015/08/05 Javascript
莱鸟介绍window.print()方法
2016/01/06 Javascript
深入浅析JavaScript中的Function类型
2016/07/09 Javascript
Node.js制作简单聊天室
2017/01/12 Javascript
vue3.0 CLI - 3.2 路由的初级使用教程
2018/09/20 Javascript
JS实现简单随机3D骰子
2019/10/24 Javascript
提升Python程序运行效率的6个方法
2015/03/31 Python
Python中使用dom模块生成XML文件示例
2015/04/05 Python
Eclipse中Python开发环境搭建简单教程
2016/03/23 Python
用python中的matplotlib绘制方程图像代码
2019/11/21 Python
python 计算概率密度、累计分布、逆函数的例子
2020/02/25 Python
python 将列表里的字典元素合并为一个字典实例
2020/09/01 Python
使用Python实现NBA球员数据查询小程序功能
2020/11/09 Python
Pytorch模型迁移和迁移学习,导入部分模型参数的操作
2021/03/03 Python
国外的一些J2EE面试题一
2012/10/13 面试题
介绍一下Ruby中的对象,属性和方法
2012/07/11 面试题
物流仓储实习自我鉴定
2013/09/25 职场文书
护理专业个人求职简历的自我评价
2013/10/13 职场文书
《故乡》教学反思
2014/04/10 职场文书
人事主管岗位职责说明书
2014/07/30 职场文书
2014教师党员个人自我评议
2014/09/20 职场文书
2015年学生会部门工作总结
2015/04/21 职场文书
导游词之白茶谷九龙峡
2019/10/23 职场文书
python文件目录操作之os模块
2021/05/08 Python
在 SQL 语句中处理 NULL 值的方法
2021/06/07 SQL Server