Angular复习笔记5-指令

在Angular中,指令是一个重要的概念,它作用在特定的DOM元素上,可以扩展这个元素的功能,为元素增加新的行为。本质上,组件可以被理解为一种带有视图的指令。组件继承自指令,是指令的一个子类,通常被用来构造UI控件。

指令的使用并不复杂,它与HTML元素属性的使用方式相似。不同的是,HTML语法标准为HTML元素预定义了特定的属性,浏览器遵循这一语法标准,实现了这些属性的内置行为。语法标准预定义的属性是有限的、不可扩展的,而Angular中的指令是可自定义的、可任意扩展的,这在一定程度上弥补了标准HTML元素属性功能的不足。

指令分类

在angular中指令分为三类:属性型指令,结构型指令和组件。

属性型指令

顾名思义,属性指令是以元素属性的形式来使用的指令。与HTML元素的内置属性不同,指令是Angular对HTML元素属性的扩展,浏览器本身不能识别这些指令,指令仅在Angular环境中才能被识别使用。属性指令通常被用来改变元素的外观和行为,如在第7章中介绍过的Angular内置指令NgStyle,它可以基于组件的状态来动态设置目标元素的样式。

结构型指令

结构指令可以用来改变DOM树的结构。结构指令可以根据模板表达式的值,增加或删除DOM元素,从而改变DOM的布局。结构指令与属性指令的使用方式相同,都是以元素属性的形式来使用的。两者的区别在于使用场景不同,属性指令用来改变元素的外观和行为,而结构指令用来改变DOM树的结构。
以Angular内置的结构指令NgIf为例,使用NgIf指令需要为指令绑定一个表达式,当表达式值为true时,该DOM元素及其子元素被添加至DOM中;当表达式值为false时,元素从DOM中被移除。示例代码如下:

上面的代码当condition的值为true时会显示p元素,反之p元素会从DOM中移除。

组件

组件继承自指令,它的代码结构与指令也是相似的,不同之处在于组件有一个自描述的模板,并且组件是用@Component来修饰,而指令需要一个宿主元素,用@Directive来描述。

组件与指令的部分生命周期钩子函数相同:

尽管组件与指令有相似的结构和一些相同的生命周期钩子方法,但是它们也有一些不同点。不同于属性指令和结构指令,组件不是以HTML元素属性的形式使用的,而是以自定义标签的形式使用的,原因在于组件带有模板。组件可作为对HTML元素的扩展,将自身的模板视图插入DOM中;而属性指令和结构指令是对HTML元素属性的扩展,其作用是扩展已有DOM元素的行为和样式,或者改变这些元素在DOM中的结构。

自定义属性型指令

一个属性指令需要一个控制器类,该控制器类使用@Directive装饰器来装饰。@Directive装饰器指定了用以标记指令所关联属性的选择器,控制器类则实现了指令所对应的特定行为。

首先需要从@angular/core中引入Directive和ElementRef。前者包含了修饰指令的装饰器@Directive,后者通过指令的构造函数传入,代表指令修饰的DOM元素宿主。

@Directive({
selector: '[appFirst]'
})
export class FirstDirective implements OnInit {
constructor(el: ElementRef) { }
ngOnInit(): void { } }

上面的代码便是创建了一个指令,我们需要在@Directive中定义这个指令的选择器,选择器的规则遵循CSS选择器标准,例如上面的选择器是[appFirst],表示该指令会以属性的方式附着在元素上面。

Angular会为每一个匹配的DOM元素创建一个指令实例,同时将ElementRef作为参数注入到控制器构造函数。使用ElementRef服务,可以在代码中通过其nativeElement属性直接访问DOM元素,这样就可以通过DOM API设置元素的背景色:

@Directive({
selector: '[appFirst]'
})
export class FirstDirective implements OnInit {
constructor(private el: ElementRef) { }
ngOnInit(): void {
console.log(this.el);
this.el.nativeElement.style.backgroundColor = 'red';
} }

为指令绑定输入

在上述的代码中指令为宿主设置的颜色是固定的,如果要想动态的变更颜色,有两个思路:

第一,设置一个@Input输入属性,并将这个属性定义为set函数:

@Directive({
selector: '[appFirst]'
})
export class FirstDirective {
@Input() set backgroundColor(color: string) {
if (color) {
this.el.nativeElement.style.backgroundColor = color;
}
}
constructor(private el: ElementRef) { } }

第二,指令实现onChanges接口,在接口中处理逻辑:

@Directive({
selector: '[appFirst]'
})
export class FirstDirective implements OnChanges {
@Input() backgroundColor: string;
ngOnChanges(changes: SimpleChanges): void {
this.el.nativeElement.style.backgroundColor = this.backgroundColor;
}
constructor(private el: ElementRef) { } }

然后在宿主中使用这个指令:

 <p appFirst [backgroundColor]="color" matLine>template</p>

在宿主中需要定义一个color变量并且改变这个color变量的值,这里就不演示了。

响应用户操作

可以使用@HostListener来响应用户发出的事件。@HostListener指向使用指令的DOM元素,使得DOM元素的事件与指令关联起来。@HostListener是另一种动态设置的方案,相比较前面那种@Input set输入属性的方式还有生命周期钩子的方式,这种方式是从响应用户发出的事件的角度执行的。

//.....其他代码....
@HostListener('click')
onClick(){
//.....代码逻辑....
}

自定义结构型指令

不同于属性型指令,属性型指令会在构造函数中传入一个ElementRef来表示它的宿主DOM元素,而结构型指令需要在构造器中传入两个参数,一个是TempleteRef,另一个是ViewContainerRef.这是因为被结构型指令修饰的DOM元素会被angular转译成一个<ng-temeplate>元素:

<span *ngIf="condition">can you see it?</span>

上面的代码会被angular转译为:

<ng-temeplate [ngIf]="condition">
<span>can you see it?</span>
</ng-template>

可以看出结构型指令会被转译成一个属性型的指令。

所以,结构型指令需要传入一个TemeplateRef的服务来访问到这个组件模板(被转译成的ng-template)。至于另一个ViewContainerRef,这个服务是可以从DOM中创建或者删除一个TemplateRef所代表的模板元素,要取决于对结构型指令求值的boolean值(因为给结构型指令绑定的表达式必须是一个boolean类型的表达式)。

下面代码简单定义了一个结构型的指令:

@Directive({
selector: '[appFirst]'
})
export class FirstDirective {
constructor(templ: TemplateRef<any>, container: ViewContainerRef) { }
@Input() condition: boolean;
}

看起来和属性型的指令差不多,不同之处在于构造函数传入的参数类型不同。使用上也和属性型指令差不多,需要注意的就是ViewContainerRef的两个方法,这两个方法都是用来操作指令中的TemplateRef所指向的模板的:

createEmbeddedView():需要传入一个TemplateRef类型的参数,表示根据TemplateRef创建一个内嵌的视图模板。

clear():将TemplateRef视图模板中删除。

Angular复习笔记5-指令的更多相关文章

  1. Angular复习笔记7-路由(下)

    Angular复习笔记7-路由(下) 这是angular路由的第二篇,也是最后一篇.继续上一章的内容 路由跳转 Web应用中的页面跳转,指的是应用响应某个事件,从一个页面跳转到另一个页面的行为.对于使 ...

  2. Angular复习笔记7-路由(上)

    Angular复习笔记7-路由(上) 关于Angular路由的部分将分为上下两篇来介绍.这是第一篇. 概述 路由所要解决的核心问题是通过建立URL和页面的对应关系,使得不同的页面可以用不同的URL来表 ...

  3. angular复习笔记4-模板

    Angular复习笔记4-模板 简介 模板是一种自定义的标准化页面,通过模板和模板中的数据结合,可以生成各种各样的网页.在Angular中,模板的默认语言是HTML,几乎所有的HTML语法在模板中都是 ...

  4. Angular复习笔记6-依赖注入

    Angular复习笔记6-依赖注入 依赖注入(DependencyInjection)是Angular实现重要功能的一种设计模式.一个大型应用的开发通常会涉及很多组件和服务,这些组件和服务之间有着错综 ...

  5. angular复习笔记1-开篇

    前言 学习和使用angular已经有一段时间了.这段时间利用angular做了一个系统,算是对angular有了一个全面的认识,趁着现在有一些时间,把angular的一些知识记录一下. 安装angul ...

  6. angular复习笔记3-组件

    组件Component 组件是构成angular应用的核心,angular的有序运行依赖于组件的协同工作,组件之于angular应用就像是汽车和汽车零部件的意思. 概述 近几年的前端发展迅速,各种工程 ...

  7. angular复习笔记2-架构总览

    angular架构总览 一个完整的Angular应用主要由6个重要部分构成,分别是:组件.模板.指令.服务.依赖注入和路由.这些组成部分各司其职,而又紧密协作,它们的关系如图所示. 与用户直接交互的是 ...

  8. Angular 学习笔记——自定义指令之间的交互

    <!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <met ...

  9. Angular 学习笔记——自定义指令

    <!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...

随机推荐

  1. 倍增&矩阵乘法 专题复习

    倍增&矩阵乘法 专题复习 PreWords 这两个基础算法我就不多说啦,但是还是要介绍一下" 广义矩阵 "乘法 其实就是把矩阵换成取\(max\),然后都一样... 据神仙 ...

  2. mysql将多条结果拼接成一条结果

    1,实际数据 SELECT resource_id, resource_type FROM res_resource_mount 2,拼接之后数据 SELECT c.resource_id, GROU ...

  3. 【Beta】Scrum meeting 6 & 助教参会记录

    github 本此会议项目由PM召开,召开时间为5月13日晚上10点 召开时长15分钟 任务表格 姓名 当前任务 下阶段任务 袁勤 初步实现后端题库功能 优化后端 彭一夫 向数据库导入新题 查看评论功 ...

  4. git推送本地分支到远程仓库并在远程仓库创建新分支

    $ git push <远程主机名> <本地分支名>:<远程分支名> git push master test:test #master 为设置的远程仓库别名,第一 ...

  5. Centos 7.x卸载ibus黑屏修复及fcitx搜狗拼音安装方法

    ibus黑屏修复 百度出来的fcitx安装方法,都要卸载ibus,如果没有注意同时卸载掉的依赖包的话,gnome桌面中的一些关键库也没被卸载. 修复方法很简单,重新安装Gnome sudo yum - ...

  6. kaggle, gmail, 烟雨朦胧

    kaggle, gmail, 烟雨朦胧 刚才为了体验kaggle,用gmail重新登录,需要验证十几年前在桂林使用的手机号,竟然找到了,终于又可以上了. 那是一个在烟雨江南里努力奋斗而又迷失自我不堪回 ...

  7. eclispe: 修改所有文件默认编码为UTF-8

    1.修改 workspace text file encoding 依次点击windows -> Preferences -> general -> Workspace,修改如图的编 ...

  8. 【Python】解析Python中的文件操作

    目录结构: contents structure [-] 简介 Python中的文件类型 内置函数的文件操作 open()函数 Mode 创建文本文件 读取文本文件 循环文件对象 关闭文件 With语 ...

  9. yum提示problem making ssl connection的解决办法

    yum缓存提示problem making ssl connection的解决办法 缺少ssl证书认证本地获取的问题导致,解决办法如下: 执行命令:yum install -y ca-certific ...

  10. Class-SP:Order.cs

    ylbtech-Class-SP:Order.cs 1. 返回顶部 1.GoodsType.cs 货品类别 using System; using System.Collections.Generic ...