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获取父节点方法
Aug 20 Javascript
UI Events 用户界面事件
Jun 27 Javascript
原生js实现查找/添加/删除/指定元素的class
Apr 12 Javascript
Javascript变量作用域详解
Dec 06 Javascript
Windows8下搭建Node.js开发环境教程
Sep 03 Javascript
js实现的动画导航菜单效果代码
Sep 10 Javascript
基于Bootstrap使用jQuery实现简单可编辑表格
May 04 Javascript
微信开发 微信授权详解
Oct 21 Javascript
JavaScript求一个数组中重复出现次数最多的元素及其下标位置示例
Jul 23 Javascript
使用vue 国际化i18n 实现多实现语言切换功能
Oct 11 Javascript
webpack4 SplitChunks实现代码分隔详解
May 23 Javascript
jQuery+css实现的点击图片放大缩小预览功能示例【图片预览 查看大图】
May 29 jQuery
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 ci框架中加载css和js文件失败的解决方法
2014/03/03 PHP
利用PHP访问带有密码的Redis方法示例
2017/02/09 PHP
PHP实现QQ、微信和支付宝三合一收款码实例代码
2018/02/19 PHP
CI框架附属类用法分析
2018/12/26 PHP
laravel 实现上传图片到本地和前台访问示例
2019/10/21 PHP
Javascript中的数学函数
2007/04/04 Javascript
JQuery的Alert消息框插件使用介绍
2010/10/09 Javascript
JavaScript mapreduce工作原理简析
2012/11/25 Javascript
location对象的属性和方法应用(解析URL)
2013/04/12 Javascript
js页面跳转的问题(跳转到父页面、最外层页面、本页面)
2013/08/14 Javascript
jQuery+CSS3+Html5实现弹出层效果实例代码(附源码下载)
2016/05/16 Javascript
jQuery自定义数值抽奖活动代码
2016/06/11 Javascript
浅谈JavaScript中变量和函数声明的提升
2016/08/09 Javascript
jquery实现点击页面回到顶部
2016/11/23 Javascript
vue+axios实现登录拦截的实例代码
2017/05/22 Javascript
JavaScript实现京东购物放大镜和选项卡效果的方法分析
2018/07/05 Javascript
基于vue-router 多级路由redirect 重定向的问题
2018/09/03 Javascript
element-ui多文件上传的实现示例
2019/04/10 Javascript
JavaScript 事件代理需要注意的地方
2020/09/08 Javascript
PHP实现发送和接收JSON请求
2018/06/07 Python
python顺序的读取文件夹下名称有序的文件方法
2018/07/11 Python
python处理multipart/form-data的请求方法
2018/12/26 Python
python多线程实现同时执行两个while循环的操作
2020/05/02 Python
django实现日志按日期分割
2020/05/21 Python
python爬虫可以爬什么
2020/06/16 Python
使用Python pip怎么升级pip
2020/08/11 Python
日本必酷网络直营店:Biccamera
2019/03/23 全球购物
Guess美国官网:美国知名服装品牌
2019/04/08 全球购物
社区母亲节活动方案
2014/03/05 职场文书
会议主持词
2014/03/17 职场文书
旅游节目策划方案
2014/05/26 职场文书
2014小学教师个人工作总结
2014/11/10 职场文书
志愿者事迹材料
2014/12/26 职场文书
2016年法制宣传月活动总结
2016/04/01 职场文书
mysql5.7使用binlog 恢复数据的方法
2021/06/03 MySQL
Spring Boot 实现敏感词及特殊字符过滤处理
2021/06/29 Java/Android