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 相关文章推荐
jquery事件机制扩展插件 jquery鼠标右键事件
Dec 21 Javascript
JavaScript设置body高度为浏览器高度的方法
Feb 09 Javascript
jQuery中常用的遍历函数用法实例总结
Sep 01 Javascript
JS实现的不规则TAB选项卡效果代码
Sep 18 Javascript
js实现滚动条滚动到页面底部继续加载
Dec 19 Javascript
原生Javascript插件开发实践
Jan 18 Javascript
基于vue.js实现侧边菜单栏
Mar 20 Javascript
Vue键盘事件用法总结
Apr 18 Javascript
node.js监听文件变化的实现方法
Apr 17 Javascript
在Koa.js中实现文件上传的接口功能
Oct 08 Javascript
vue h5移动端禁止缩放代码
Oct 28 Javascript
vscode 调试 node.js的方法步骤
Sep 15 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中的Memcache详解
2014/04/05 PHP
php curl 获取https请求的2种方法
2015/04/27 PHP
PHP中的事务使用实例
2015/05/26 PHP
PHP的PDO大对象(LOBs)
2019/01/27 PHP
jquery 无限级联菜单案例分享
2013/03/26 Javascript
jQuery/CSS3图片特效插件整理推荐
2014/12/07 Javascript
node.js中的fs.writeSync方法使用说明
2014/12/15 Javascript
使用AngularJS创建单页应用的编程指引
2015/06/19 Javascript
js老生常谈之this,constructor ,prototype全面解析
2016/04/05 Javascript
javascript用正则表达式过滤空格的实现代码
2016/06/14 Javascript
jQuery中的一些小技巧
2017/01/18 Javascript
nodejs判断文件、文件夹是否存在及删除的方法
2017/11/10 NodeJs
form表单数据封装成json格式并提交给服务器的实现方法
2017/12/14 Javascript
在Vue组件中使用 TypeScript的方法
2018/02/28 Javascript
对Angular中单向数据流的深入理解
2018/03/31 Javascript
序列化模块json代码实例详解
2020/03/03 Javascript
[01:15:12]DOTA2上海特级锦标赛主赛事日 - 1 败者组第一轮#4Newbee VS CDEC
2016/03/03 DOTA
python处理图片之PIL模块简单使用方法
2015/05/11 Python
python中利用xml.dom模块解析xml的方法教程
2017/05/24 Python
Python网络爬虫中的同步与异步示例详解
2018/02/03 Python
解决在Python编辑器pycharm中程序run正常debug错误的问题
2019/01/17 Python
python 实现快速生成连续、随机字母列表
2019/11/28 Python
使用python 对验证码图片进行降噪处理
2019/12/18 Python
python字符串替换re.sub()实例解析
2020/02/09 Python
python 模拟登陆163邮箱
2020/12/15 Python
PyQt5中QSpinBox计数器的实现
2021/01/18 Python
Schutz鞋官方网站:Schutz Shoes
2017/12/13 全球购物
电大自我鉴定范文
2013/10/01 职场文书
我的动漫时代的创业计划书范文
2014/01/27 职场文书
高中军训感想300字
2014/03/04 职场文书
乡镇党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
小兵张嘎观后感300字
2015/06/03 职场文书
python xlwt模块的使用解析
2021/04/13 Python
Python实现简繁体转换
2021/06/07 Python
Java Lambda表达式常用的函数式接口
2022/04/07 Java/Android
el-form每行显示两列底部按钮居中效果的实现
2022/08/05 HTML / CSS