角度指令实用指南

本文重点介绍Angular指令-它们是什么,如何使用它们以及如何构建自己的指令。

指令可能是Angular应用程序中最重要的部分,如果我们考虑一下,最常用的Angular单元即组件实际上就是指令。

Angular组件不只是带有模板的指令。 当我们说组件是Angular应用程序的构建块时,实际上是在说指令是Angular应用程序的构建块。

基本概述

指令的核心是一个函数,只要Angular编译器在DOM中找到指令,该指令就执行。 Angular指令用于通过赋予其新语法来扩展HTML的功能。 每个指令都有一个名称-可以是Angular预定义的名称(例如ng-repeat ,也可以是自定义名称,可以将其称为任何名称。 每个指令都决定了可以在哪里使用它:在elementattributeclasscomment

默认情况下,从Angular版本2起,Angular指令分为三种不同的类型:

组件

如前所述,组件只是带有模板的指令。 在后台,它们使用指令API,并为我们提供了一种更清晰的方式来定义它们。

其他两种指令类型没有模板。 相反,它们是专门为DOM操作量身定制的。

属性指令

属性指令通过更改其行为和外观来操纵DOM。

我们使用属性指令将条件样式应用于元素,显示或隐藏元素或根据不断变化的属性动态改变组件的行为。

结构指令

这些是专门为创建和销毁DOM元素而量身定制的。

一些属性指令(例如hidden ,显示或隐藏元素)基本上保持了DOM的原样。 但是结构化的Angular指令对DOM的友好度要低得多,因为它们从DOM中添加或完全删除了元素。 因此,在使用它们时,我们必须格外小心,因为实际上是在更改HTML结构。

使用现有的角度指令

在Angular中使用现有指令非常容易,并且如果您过去曾经编写过Angular应用程序,我敢肯定您已经使用了它们。 ngClass指令是现有Angular属性指令的一个很好的例子:

<p [ngClass]="{'blue'=true, 'yellow'=false}">
    Angular Directives Are Cool!
</p>

<style>
    .blue{color: blue}
    .yellow{color: yellow}
</style>

因此,通过在下面的示例中使用ngClass指令 ,我们实际上将blue类添加到了我们的段落中,而明确地未添加yellow 。 因为我们要更改类的外观,而不是更改实际的HTML结构,所以这显然是一个属性指令。 但是Angular还提供了现成的结构化指令,例如ngIf

@Component({
  selector: 'ng-if-simple',
  template: `
    <button (click)="show = !show">{{show ? 'hide' : 'show'}}</button>
    show = {{show}}
    <br>
    <div *ngIf="show">Text to show</div>
`
})

class NgIfSimple {
  show: boolean = true;
}

在此示例中,我们使用ngIf指令通过按钮添加或删除文本。 在这种情况下,HTML结构本身会受到影响,因此它显然是结构指令。

有关可用Angular指令的完整列表,我们可以查看官方文档

如我们所见,使用Angular指令非常简单。 Angular指令的真正力量在于创建自己的指令的能力。 Angular提供了一个干净而简单的API来创建自定义指令,这就是我们将在以下各节中介绍的内容。

创建一个属性指令

创建指令类似于创建组件。 但是在这种情况下,我们使用@Directive装饰器。 对于我们的示例,我们将创建一个名为“ my-error-directive”的指令,该指令将以红色突出显示表示错误的元素背景。

对于我们的示例,我们将使用Angular 2 quickstart软件包 。 我们只需要克隆存储库,然后运行npm installnpm start 。 它将为我们提供可用于实验的样板应用程序。 我们将在该样板之上构建示例。

app.myerrordirective.ts ,在src/app文件夹中创建一个名为app.myerrordirective.ts的文件,并向其中添加以下代码:

import {Directive, ElementRef} from '@angular/core';

@Directive({
    selector:'[my-error]'
})

export class MyErrorDirective{
    constructor(elr:ElementRef){
        elr.nativeElement.style.background='red';
    }
}

@angular/core导入Directive ,我们可以使用它。 首先,我们需要一个选择器,该选择器为指令指定名称。 在这种情况下,我们称之为my-error

最佳实践表明,在命名Angular指令时,我们始终使用前缀。 这样,我们确保避免与任何标准HTML属性发生冲突。 我们也不应使用ng前缀。 那个是Angular使用的,我们不想将我们自定义创建的Angular指令与Angular预定义的指令混淆。 在此示例中,我们的前缀是my-

然后,我们创建了一个类MyErrorDirective 。 要访问我们DOM的任何元素,我们需要使用ElementRef 。 由于它也属于@angular/core包,因此只需将其与Directive一起导入并使用即可。

然后,我们添加了代码以突出显示类的构造函数。

为了能够使用这个新创建的指令,我们需要将其添加到app.module.ts文件的声明中:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MyErrorDirective } from './app.myerrordirective';

import { AppComponent }  from './app.component';

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent, MyErrorDirective ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

最后,我们要利用刚刚创建的指令。 为此,让我们导航到app.component.ts文件并添加以下内容:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `<h1 my-error>Hello {{name}}</h1>`,
})
export class AppComponent  { name = 'Angular'; }

最终结果类似于以下内容:

Angular指令:属性指令示例

创建结构指令

在上一节中,我们看到了如何使用Angular创建属性指令。 创建结构行为的方法是完全相同的。 我们使用指令的代码创建一个新文件,然后将其添加到声明中,最后在组件中使用它。

对于我们的结构指令,我们将实现ngIf指令的副本。 这样,我们不仅将实现指令,而且还将了解Angular指令如何处理幕后事物。

让我们从我们的app.mycustomifdirective.ts文件开始:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({
    selector: '[myCustomIf]'
})

export class MyCustomIfDirective {

    constructor(
        private templateRef: TemplateRef<any>,
        private viewContainer: ViewContainerRef) { }

    @Input() set myCustomIf(condition: boolean) {
        if (condition) {
            this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
            this.viewContainer.clear();
        }
    }
}

如我们所见,我们为此使用了几个不同的导入,主要是: InputTemplateRefViewContainerRefInput装饰器用于将数据传递到组件。 TemplateRef用来实例化嵌入式视图 。 嵌入式视图表示要渲染的布局的一部分,并且已链接到模板。 最后, ViewContainerRef是一个容器,可以在其中附加一个或多个视图。 这些组件一起工作如下:

指令通过注入ViewContainerRef来访问视图容器。 通过调用ViewContainerRefcreateEmbeddedView方法并传入模板,可以创建嵌入式视图并将其附加到视图容器。 我们要使用指令附带的模板,所以我们传入注入的TemplateRef—来自Rangle.io的Angular 2培训

接下来,我们将其添加到声明器中:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MyErrorDirective } from './app.myerrordirective';
import { MyCustomIfDirective } from './app.mycustomifdirective';

import { AppComponent }  from './app.component';

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent, MyErrorDirective, MyCustomIfDirective ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

我们在组件中使用它:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `<h1 my-error>Hello {{name}}</h1>
         <h2 *myCustomIf="condition">Hello {{name}}</h2>
             <button (click)="condition = !condition">Click</button>`,
})

export class AppComponent  {
    name = 'Angular';
    condition = false;    
}

结构指令提供的这种方法可能非常有用,例如当我们必须根据不同用户的权限向他们显示不同信息时。 例如,站点管理员应该能够查看和编辑所有内容,而普通用户则不能。 如果我们使用属性指令将私有信息加载到DOM中,那么普通用户和所有与此相关的用户都可以访问它。

角度指令:属性与结构

我们已经研究了属性和结构指令。 但是我们什么时候应该使用其中一个?

答案可能会令人困惑,我们可能会因为解决了我们的问题而最终选择了错误的答案。 但是有一条简单的规则可以帮助我们选择正确的规则。 基本上,如果在DOM不可见时具有指令的元素在DOM中仍然有用,那么我们绝对应该保留它。 在这种情况下,我们使用诸如hidden的属性指令。 但是,如果该元素没有用处,则应将其删除。 但是,我们必须小心避免一些常见的陷阱。 我们必须避免因为总是更容易隐藏总是隐藏元素的陷阱。 这将使DOM变得更加复杂,并可能对整体性能产生影响。 还应避免总是删除和重新创建元素的陷阱。 它绝对更干净,但是会牺牲性能。

总而言之,应仔细分析每种情况,因为理想的解决方案始终是对您的应用程序结构,行为和性能影响最小的解决方案。 该解决方案可能是属性指令,结构指令,或者在最常见的情况下,是两者之间的折衷。

结论

在本文中,我们研究了Angular指令(Angular应用程序的核心)。 我们研究了不同类型的指令,并了解了如何创建适合我们需求的自定义指令。

我希望本文能够帮助您使用Angular指令并开始运行。 如有任何疑问,请随时使用下面的评论部分。

From: https://www.sitepoint.com/practical-guide-angular-directives/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值