Angular 8 指令


Angular 8 指令是与你的应用程序交互的 DOM 元素。一般来说,指令是 打字稿 功能。当这个函数执行时 Angular 编译器在 DOM 元素中检查它。 Angular 指令以 ng- where ng 代表 Angular 并扩展 HTML 标签 @指示 装饰师。

指令使逻辑可以包含在 Angular 模板中。 Angular指令可以分为三类,它们如下:

属性指令

用于为现有 HTML 元素添加新属性以更改其外观和行为。

<HTMLTag [attrDirective]='value' />

例如,

<p [showToolTip]='Tips' />

Here, 显示工具提示 引用一个示例指令,当在 HTML 元素中使用时,将在用户悬停 HTML 元素时显示提示。

结构性指令

用于在当前 HTML 文档中添加或删除 DOM 元素。

<HTMLTag [structuralDirective]='value' />

例如,

<div *ngIf="isNeeded"> 
    Only render if the *isNeeded* value has true value.
</div>

Here, ngIf 是一个内置指令,用于在当前 HTML 文档中添加或删除 HTML 元素。 Angular 提供了许多内置指令,我们将在后面的章节中学习。

基于组件的指令

组件可以用作指令。每个组件都有 输入 and 输出 在组件及其父 HTML 元素之间传递的选项。

<component-selector-name [input-reference]="input-value"> ... </component-selector-name>

例如,

<list-item [items]="fruits"> ... </list-item>

Here, 项目清单 是一个组件并且 items 是输入选项。我们将在后面的章节中学习如何创建组件和高级用法。

在转到这个主题之前,让我们创建一个示例应用程序 (指令应用程序) 在 Angular 8 中进行学习。

打开命令提示符并使用以下命令创建新的 Angular 应用程序:

cd /go/to/workspace 
ng new directive-app 
cd directive-app

Create a test 使用Angular CLI的组件如下:

ng generate component test

上面新建了一个组件,输出如下:

CREATE src/app/test/test.component.scss (0 bytes) CREATE src/app/test/test.component.html (19 bytes) CREATE src/app/test/test.component.spec.ts (614 bytes) 
CREATE src/app/test/test.component.ts (262 bytes) UPDATE src/app/app.module.ts (545 bytes)

使用以下命令运行应用程序:

ng serve

DOM 概述


让我们简要地看一下 DOM 模型。 DOM 用于定义访问文档的标准。通常,HTML DOM 模型构造为对象树。它是访问 html 元素的标准对象模型。

我们可以在 Angular 8 中使用 DOM 模型,原因如下:

  • 我们可以使用 DOM 元素轻松导航文档结构。
  • 我们可以很容易地添加 html 元素。
  • 我们可以轻松更新元素及其内容。

结构性指令


结构性指令改变结构 DOM 通过添加或删除元素。它用 * 符号表示,带有三个预定义的指令 NgIf, NgFor and NgSwitch .让我们简要地一一了解。

NgIf 指令

NgIf 指令用于根据条件变为真或假来显示或隐藏应用程序中的数据。我们可以将其添加到你模板中的任何标签中。

让我们试试 ngIf 我们的指令 指令应用 应用。

将以下标签添加到 test.component.html .

<p>test works!</p> 
<div *ngIf="true">Display data</div>

将测试组件添加到你的 app.component.html 文件如下:

<app-test></app-test>

使用以下命令启动你的服务器(如果尚未启动):

ng serve

现在,运行你的应用程序,你可以看到以下响应:

NgServe

如果你设置条件 ngIf=“假” 然后,内容将被隐藏。

ngIfElse 指令

ngIfElse 类似于 ngIf 除此之外,它还提供了在故障情况下呈现内容的选项。

让我们了解如何 ngIfElse 通过做一个样本来工作。

将以下代码添加到 测试组件.ts file.

export class TestComponent implements OnInit { 
    isLogIn : boolean = false;
    isLogOut : boolean = true;
}

将以下代码添加到 test.component.html 文件如下:

<p>ngIfElse example!</p> 
<div *ngIf="isLogIn; else isLogOut"> 
    Hello you are logged in
</div>
<ng-template #isLogOut> 
    You're logged out..
</ng-template>

最后,使用以下命令启动你的应用程序(如果尚未完成):

ng serve

现在,运行你的应用程序,你可以看到以下响应:

NgApplication

Here,

isLogOut

值被分配为 true ,所以它去 else 阻止并渲染 ng-模板 .我们将学习 ng-模板 在本章后面。

ngFor 指令

ngFor 用于重复项目列表中的部分元素。

让我们通过一个示例来了解 ngFor 的工作原理。

在 test.component.ts 文件中添加列表如下:

list = [1,2,3,4,5];

Add ngFor 指令在 test.component.html 如下所示:

<h2>ngFor directive</h2> 
<ul> 
    <li *ngFor="let l of list">
        {{l}}
    </li>
</ul>

在这里,let 关键字创建了一个局部变量,并且可以在模板中的任何位置引用它。 let l 创建一个模板局部变量来获取列表元素。

最后,使用以下命令启动你的应用程序(如果尚未完成):

ng serve

现在,运行你的应用程序,你可以看到以下响应:

Ngdirective

trackBy

有时, ngFor 大型列表的性能较低。例如,当添加新项目或删除列表中的任何项目时,可能会触发多个 DOM 操作。为了迭代大型对象集合,我们使用 trackBy .

它用于跟踪添加或删除元素的时间。它由 trackBy 方法执行。它有两个参数索引和元素。索引用于唯一标识每个元素。简单示例定义如下。

让我们了解 trackBy 如何与 ngFor 通过做一个样本。

将以下代码添加到 测试组件.ts file.

export class TestComponent { 
    studentArr: any[] = [ {
        "id": 1,
        "name": "student1"
    },
    {
        "id": 2,
        "name": "student2"
    },
    {
        "id": 3, "name": "student3"
    },
    {
        "id": 4,
        "name": "student4"
    }
    ];
    trackByData(index:number, studentArr:any): number {
        return studentArr.id;
    }

Here,

我们创造了,

跟踪数据()

方法以基于 id 的独特方式访问每个学生元素。

将以下代码添加到 test.component.html 在 ngFor 中定义 trackBy 方法的文件。

<ul> 
    <li *ngFor="let std of studentArr; trackBy: trackByData">
        {{std.name}}
    </li>
</ul>

最后,使用以下命令启动你的应用程序(如果尚未完成):

ng serve

现在,运行你的应用程序,你可以看到以下响应:

Directive

在这里,应用程序将打印学生姓名。现在,应用程序正在使用学生 ID 而不是对象引用来跟踪学生对象。因此,DOM 元素不受影响。

NgSwitch 指令

NgSWitch 用于检查多个条件并保持 DOM 结构简单易懂。

让我们试试 ngSwitch 我们的指令 指令应用 应用。

将以下代码添加到 测试组件.ts file.

export class TestComponent implements OnInit {  
    logInName = 'admin';
}

在 test.component.html 文件中添加如下代码如下:

<h2>ngSwitch directive</h2> 
<ul [ngSwitch]="logInName"> 
    <li *ngSwitchCase="'user'">
        <p>User is logged in..</p>
    </li>
    <li *ngSwitchCase="'admin'">
        <p>admin is logged in</p>
    </li>
    <li *ngSwitchDefault>
        <p>Please choose login name</p>
    </li>
</ul>

最后,使用以下命令启动你的应用程序(如果尚未完成):

ng serve

现在,运行你的应用程序,你可以看到以下响应:

NgSwitch

在这里,我们定义了 登录名 as admin. 因此,它匹配第二个 SwitchCase 并打印上面的管理相关消息。

属性指令


属性指令执行 DOM 元素或组件的外观或行为。一些例子是 NgStyle、NgClass 和 NgModel。而 NgModel 是上一章解释的双向属性数据绑定。

ngStyle

ngStyle 指令用于添加动态样式。下面的示例用于将蓝色应用于段落。

让我们试试 ngStyle 我们的指令 指令应用 应用。

在下面添加内容 test.component.html file.

<p [ngStyle]="{'color': 'blue', 'font-size': '14px'}"> 
    paragraph style is applied using ngStyle
</p>

使用以下命令启动你的应用程序(如果尚未完成):

ng serve

现在,运行你的应用程序,你可以看到以下响应:

ngStyle

ngClass

ngClass 用于在 HTML 元素中添加或删除 CSS 类。

让我们试试 ngClass 我们的指令 指令应用 应用。

创建一个类 User 使用以下命令

ng g class User

你可以看到以下响应:

CREATE src/app/user.spec.ts (146 bytes) 
CREATE src/app/user.ts (22 bytes)

Move to src/app/user.ts 文件并添加以下代码:

export class User { 
    userId : number; userName : string;
}

在这里,我们创建了两个属性 userId and userName in the User class.

Open 测试组件.ts 文件并添加以下更改:

import { User } from '../user'; 
export class TestComponent implements OnInit {  
    users: User[] = [
        {
            "userId": 1,
            "userName": 'User1'
        },
        {
            "userId": 2,
            "userName": 'User2'
        },
    ];
}

在这里,我们声明了一个局部变量 users 并使用 2 个用户对象进行初始化。

Open test.component.css 文件并添加以下代码

.highlight { 
    color: red;
}

打开你的 test.component.html 文件并添加以下代码:

<div class="container"> 
    <br/>
    <div *ngFor="let user of users" [ngClass]="{
        'highlight':user.userName === 'User1'
    }">
        {{ user.userName }}
    </div>
</div>

Here,

我们已申请, ngClass for User1 所以它会突出显示 User1 .

最后,使用以下命令启动你的应用程序(如果尚未完成):

ng serve

现在,运行你的应用程序,你可以看到以下响应:

ngClass

自定义指令


Angular 提供了使用用户定义的指令扩展 angular 指令的选项,它被称为 自定义指令 .让我们在本章中学习如何创建自定义指令。

让我们尝试在我们的 指令应用 应用。

Angular CLI 提供了以下命令来创建自定义指令。

ng generate directive customstyle

执行该命令后,可以看到如下响应:

CREATE src/app/customstyle.directive.spec.ts (244 bytes) 
CREATE src/app/customstyle.directive.ts (151 bytes) UPDATE src/app/app.module.ts (1115 bytes)

Open app.module.ts。 该指令将在 应用模块 through 声明 元数据。

import { CustomstyleDirective } from './customstyle.directive'; 
@NgModule({ 
    declarations: [
        AppComponent,
        TestComponent,
        CustomstyleDirective
    ]
})

Open customstyle.directive.ts 文件并添加以下代码:

import { Directive, ElementRef } from '@angular/core'; 
@Directive({ 
    selector: '[appCustomstyle]'
}) 
export class CustomstyleDirective {
    constructor(el: ElementRef) {
        el.nativeElement.style.fontSize = '24px';
    }
}

Here, 构造函数 方法使用获取元素 自定义样式指令 as el .然后,它访问 el 的样式并将其字体大小设置为 24px 使用 CSS 属性。

最后,使用以下命令启动你的应用程序(如果尚未完成):

ng serve

现在,运行你的应用程序,你可以看到以下响应:

Custom directives

ng-模板

ng-模板 用于创建动态和可重用的模板。它是一个虚拟元素。如果你编译你的代码 ng-模板 然后在 DOM 中转换为注释。

例如,

让我们添加下面的代码 test.component.html page.

<h3>ng-template</h3> 
<ng-template>ng-template tag is a virtual element</ng-template>

如果你运行该应用程序,那么它将只打印 h3 元素。检查你的页面来源,模板显示在评论部分,因为它是一个虚拟元素,因此它不会呈现任何内容。我们需要使用 ng-模板 以及 Angular 指令。

通常,指令会发出与其关联的 HTML 标记。有时,我们不需要标签,只需要内容。例如,在下面的示例中,将发出 li。

<li *ngFor="let item in list">{{ item }}</li>

我们可以用 ng-模板 安全地跳过 li tag.

带有结构指令的 ng-template

ng-模板 应始终在内部使用 ngIf, ngFor or ngSwitch 渲染结果的指令。

让我们假设简单的代码。

<ng-template [ngIf]=true> 
    <div><h2>ng-template works!</h2></div>
</ng-template>

Here, if ngIf 条件为真,它将打印 div 元素内的数据。同样,你可以使用 ngFor and ngSwitch 指令也是如此。

NgForOf 指令

ngForOf 也是一个结构指令,用于呈现集合中的项目。下面的例子用来展示 ngForOf 里面的指令 ng-模板 .

import { Component, OnInit } from '@angular/core'; 
@Component({ 
    selector: 'app-test',
    template: `
    <div>
    <ng-template ngFor let-item [ngForOf]="Fruits" let-i="index">
    <p>{{i}}</p>
    </ng-template>
    </div>`
    ,
    styleUrls: ['./test.component.css']
}) 
export class TestComponent implements OnInit { 
    Fruits = ["mango","apple","orange","grapes"];
    ngOnInit()
    {
    }
}

如果运行应用程序,它将显示每个元素的索引,如下所示:

0 
1 
2 
3

组件指令


组件指令基于组件。实际上,每个组件都可以用作指令。组件提供@输入 和@输出 装饰器来在父子组件之间发送和接收信息。

让我们尝试在我们的 指令应用 应用。

创建一个新的 子组件 使用以下命令:

ng generate component child
CREATE src/app/child/child.component.html (20 bytes) CREATE src/app/child/child.component.spec.ts (621 bytes) 
CREATE src/app/child/child.component.ts (265 bytes) CREATE src/app/child/child.component.css (0 bytes) UPDATE src/app/app.module.ts (466 bytes)

Open child.component.ts 并添加以下代码:

@输入() userName: string;

在这里,我们为 子组件 .

Open child.component.html 并添加以下代码:

<p>child works!</p> 
<p>Hi {{ userName }}</p>

在这里,我们使用值 userName 来欢迎用户。

Open 测试组件.ts 并添加以下代码:

name: string = 'Peter';

Open test.component.html 并添加以下代码:

<h1>Test component</h1> 
<app-child [userName]="name"><app-child>

在这里,我们使用 应用组件 在 - 的里面 测试组件 作为具有输入属性的指令。

最后,使用以下命令启动你的应用程序(如果尚未完成):

ng serve

现在,运行你的应用程序,你可以看到以下响应:

[](图像/directive-app/component_as_directive.PNG"

工作示例

让我们在我们的 费用经理 申请列出费用条目。

打开命令提示符并转到项目根文件夹。

cd /go/to/expense-manager

启动应用程序。

ng serve

创建一个新组件, 费用条目列表组件 使用以下命令:

ng generate component ExpenseEntryList

输出如下:

CREATE src/app/expense-entry-list/expense-entry-list.component.html (33 bytes) 
CREATE src/app/expense-entry-list/expense-entry-list.component.spec.ts (700 bytes) 
CREATE src/app/expense-entry-list/expense-entry-list.component.ts (315 bytes) 
CREATE src/app/expense-entry-list/expense-entry-list.component.css (0 bytes) 
UPDATE src/app/app.module.ts (548 bytes)

在这里,该命令创建 ExpenseEntryList 组件并更新必要的代码 应用模块 .

Import 费用分录 into 费用条目列表组件 零件 (src/app/expense-entry-list/expense-entry-list.component)

import { ExpenseEntry } from '../expense-entry';

添加方法, 获取费用条目() 返回费用条目(模拟项目)列表 ExpenseEntryListComponent (src/app/expense-entry-list/expense-entry-list.component)

getExpenseEntries() : ExpenseEntry[] { 
    let mockExpenseEntries : ExpenseEntry[] = [
        { id: 1,
            item: "Pizza",
            amount: Math.floor((Math.random() * 10) + 1),
            category: "Food",
            location: "Mcdonald",
            spendOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10),
            createdOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10) },
        { id: 1,
            item: "Pizza",
            amount: Math.floor((Math.random() * 10) + 1),
            category: "Food",
            location: "KFC",
            spendOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10),
            createdOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10) },
        { id: 1,
            item: "Pizza",
            amount: Math.floor((Math.random() * 10) + 1),
            category: "Food",
            location: "Mcdonald",
            spendOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10),
            createdOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10) },
        { id: 1,
            item: "Pizza",
            amount: Math.floor((Math.random() * 10) + 1),
            category: "Food",
            location: "KFC",
            spendOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10),
            createdOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10) },
        { id: 1,
            item: "Pizza",
            amount: Math.floor((Math.random() * 10) + 1),
            category: "Food",
            location: "KFC",
            spendOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10),
            createdOn: new Date(2020, 4, Math.floor((Math.random() * 30) + 1), 10, 10, 10)
        },
    ];
    return mockExpenseEntries;
}

声明一个局部变量,expenseEntries 并加载如下所述的费用条目的模拟列表:

title: string; 
expenseEntries: ExpenseEntry[]; 
constructor() { } 
ngOnInit() { 
    this.title = "Expense Entry List";
    this.expenseEntries = this.getExpenseEntries();
}

打开模板文件 (src/app/expense-entry-list/expense-entry-list.component.html) 并在表格中显示模拟条目。

<!-- Page Content -->
<div class="container"> 
    <div class="row">
        <div class="col-lg-12 text-center" style="padding-top: 20px;">
            <div class="container" style="padding-left: 0px; padding-right: 0px;">
                <div class="row">
                    <div class="col-sm" style="text-align: left;">
                        {{ title }}
                    </div>
                    <div class="col-sm" style="text-align: right;">
                        <button type="button" class="btn btn-primary">Edit</button>
                    </div>
                </div>
            </div>
            <div class="container box" style="margin-top: 10px;">
                <table class="table table-striped">
                    <thead>
                        <tr>
                            <th>Item</th>
                            <th>Amount</th>
                            <th>Category</th>
                            <th>Location</th>
                            <th>Spent On</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr *ngFor="let entry of expenseEntries">
                            <th scope="row">{{ entry.item }}</th>
                            <th>{{ entry.amount }}</th>
                            <td>{{ entry.category }}</td>
                            <td>{{ entry.location }}</td>
                            <td>{{ entry.spendOn | date: 'short' }}</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

Here,

  • 使用引导表。 table and 表条纹 将根据 Boostrap 样式标准设置表格样式。

  • Used ngFor 循环 费用分录 并生成表行。

Open 应用组件 模板, src/app/app.component.html 并包括 费用条目列表组件 并删除 费用条目组件 如下所示:

... 
<app-expense-entry-list></app-expense-entry-list>

最后,应用程序的输出如下所示。

AppComponent