[Angular 基础] - 指令(directives)

news/2024/4/16 2:41:13

[Angular 基础] - 指令(directives)

这里假设已经知道如何创建 Angular 组件以及数据绑定,不然可以参考前两篇笔记:

  • [Angular 基础] - Angular 渲染过程 & 组件的创建

  • [Angular 基础] - 数据绑定(databinding)

就像中文翻译一样,directives 就是指令,它就是一系列 DOM 中存在的指令

component directive

Component 这个 declaration 就是一个最基础的指令,当运行:

import { Component } from '@angular/core';@Component({selector: 'app-my-component',template: `<p>Hello, world!</p>`,
})
export class MyComponent {}

这段代码的时候,其实就已经是在运行一个指令,这个指令做了下面几件事情:

  • @Component 表明下面声明的类是一个组件
  • selector 定义一个元素,该元素会接受当前组件内的 HTML Template
  • template 定义一个 HTML Template,将会展现在 app-my-component 这个 HTML 元素中

这就是当前需要遵从的指令,我个人理解是通知 DOM 需要渲染哪个对应的 HTML Template

以此类推,@NgModule, @Directive 等也是对应的 component directive

structural directives

structural directives 的指令是通知 DOM 增加或删除特定的 HTML 元素。目前主流的内置 structural directives 有 3 个:*ngIf, *ngFor*ngSwitch,当然,这不代表 Angular 之提供了这三个 structural directives

除此之外,开发者自己也可以创建相应的 structural directives

*ngIf

语法为 *ngIf="expression",并且这个表达式(expression) 需要返回一个 boolean。依旧使用之前的案例,这里假设点击 add server 的按钮会实现对应功能,并且需要向用户显示新的组件已经生成

对应的 View 层修改如下:

<!-- 其余显示添加 server 的 input 和 button 这里不重复了 -->
<p *ngIf="serverCreated">Sever was created, server name is {{ serverName }}</p>

对应的 VM 层修改如下:

// 新增加的变量,只有在用户点击创建 server 的 btn 时才需要显示信息serverCreated = false;onCreateServer() {this.serverCreationStatus = 'Server was created!';this.serverCreated = true;}

效果如下:

在这里插入图片描述

可以看到只有当 *ngif 里的条件为 true 时,该 DOM 才会渲染

有了 if 也会有 else 条件,这时候 V 层的代码可以这么修改:

<p *ngIf="serverCreated; else noServer">Sever was created, server name is {{ serverName }}
</p>
<ng-template #noServer><p>No server was created!</p>
</ng-template>

这里使用了一个特殊的 HTML 元素——ng-template,它主要的用途是为了搭配 structural directives 去使用的;这里 #noServer 是对 ng-template 这一元素的引用变量名

*ngIf v17 的更新

目前有一个新的语法可以重置 ngIf,它的语法就是 @for,使用方式如下:

@if (serverCreated) {
<p>Sever was created, server name is {{ serverName }}</p>
} @else {
<p>No server was created!</p>
}

其展示的效果是一样的,else if 的语法则为 @else if

这个语法是 v17 最新推出的版本,暂时还不是 production-ready,所以只在这里提一下,不会深入研究

ngFor

这是一个可以循环渲染 HTML 元素的方式,用法如下:

  • 修改 VM 层

    这里会新增一个 servers 的数组,并且在 onCreateServer 中将新添的 serverName 推到数组中去:

    servers = ['Test Server', 'Test Server2'];onCreateServer() {this.serverCreationStatus = 'Server was created!';this.servers.push(this.serverName);this.serverCreated = true;
    }
    
  • 修改 V 层

    这里就使用 *ngFor 去渲染整个数组:

    <app-server *ngFor="let server of servers"></app-server>
    

最终效果如下:

在这里插入图片描述

⚠️:这里还没有涉及到组件之间数据的传输,所以 serverName 不会动态渲染

相比较 ngIfngFor 的语法更复杂一些,它的完整语法如下:

<div*ngFor="let item of servers;trackBy: trackByFn;index as i;first as isFirst;last as isLast;even as isEven;odd as isOdd"
>{{ i }}: {{ item }}<span *ngIf="isFirst">(first)</span><span *ngIf="isLast">(last)</span><span *ngIf="isEven">(even)</span><span *ngIf="isOdd">(odd)</span>
</div>

其中 trackByFn 写在了 VM 层:

  trackByFn(index: number, item: string) {return item;}

最终展现的效果如下:

在这里插入图片描述

这里的 trackBy: trackByFn; 是 Angular 提出的一个优化方案,当它存在的时候,Angular 会检查当前返回值是否变更,如果不变更的话将不会重新渲染当前的 DOM 结点

至于 first, last 这四个是 Angular 提供的值,以便可以轻松检查这些边界条件

*ngFor v17 的更新

这个语法如下:

@for (item of items: track item.id) {
<li>{{ item.title }}</li>
}

这个语法是 v17 最新推出的版本,暂时还不是 production-ready,所以只在这里提一下,不会深入研究

ngSwitch

它的语法则类似于 switch,修改的代码如下:

<div*ngFor="let item of servers;trackBy: trackByFn;index as i;first as isFirst;last as isLast;even as isEven;odd as isOdd"
>{{ i }}: {{ item }}<span *ngIf="isFirst">(first)</span><span *ngIf="isLast">(last)</span><span *ngIf="isEven">(even)</span><span *ngIf="isOdd">(odd)</span><div [ngSwitch]="item"><p *ngSwitchCase="'red'">You picked red server!</p><p *ngSwitchCase="'blue'">You picked blue server!</p><p *ngSwitchCase="'green'">You picked green server!</p><p *ngSwitchDefault>Pick a server name</p></div>
</div>

效果如下:

在这里插入图片描述

*ngSwitch v17 的更新

这个语法如下:

@switch (expression) { @case value1:
<p>value1</p>
@case value2:
<p>value2</p>
}

这个语法是 v17 最新推出的版本,暂时还不是 production-ready,所以只在这里提一下,不会深入研究

attribute directives

structural directives 控制的是 DOM 元素的增删(是否渲染),那么 attribute directives 控制的则是渲染 DOM 中的属性

这里也会列举主流用的 3 个,同样,这也不代表 Angular 仅仅提供了这 3 个 structural directives,而且开发者同样也可以创建自己的 structural directives

ngModel

这个在之前的笔记里已经提过了,NgModel 主要提供的是双向绑定的功能

ngStyle

ngStyle 就是比较简单的控制 CSS 的地方,用法如下:

<p[ngStyle]="{'background-color': serverStatus === 'offline' ? 'red' : 'green'}"
>{{ "Server" }} with ID {{ serverId }} is {{ getServerStatus() }}
</p>

效果如下:

在这里插入图片描述

⚠️:以上代码修改在 server.component.html

❗:如果无法正确渲染,请查看 servers.component.html 中的 ngFor 是不是返回 <app-server></app-server>

⚡:ngStyle 是 attribute directives,[ngStyle] 则是使用了 property binding

🛣️:'backgound-color' 还有另一个写法是用驼峰命名法 backgroundColor,而 : 后面的也只是需要一个表达式,这里用了三元式,也可以单独创建一个方法

ngClass

这个指令则是动态更新类名,这里实现代码如下:

<p[ngStyle]="{'background-color': serverStatus === 'offline' ? 'red' : 'green'}"[ngClass]="{online: serverStatus === 'online',offline: serverStatus === 'offline'}"
>{{ "Server" }} with ID {{ serverId }} is {{ getServerStatus() }}
</p>

至于 VM 层也需要添加对应的 CSS:

@Component({selector: 'app-server',templateUrl: './server.component.html',styles: [`.online {color: cyan;}.offline {color: lightgray;}`,],
})
export class ServerComponent {}

最终效果如下:

在这里插入图片描述

总结

下面都是个人理解,对我来说 directives 解决的是下面的问题:

在这里插入图片描述

  • component directive

    • what

      其实也可以用 which 代替,目前接触过的有两个 directives:

      • @Component 来说是哪个 HTML Template

      • @NgModule 是哪个对应的 NgModule

    • where

      这个目前接触到的是 @Component 中的 selector,这里决定哪里会渲染对应的指代组件

  • structural directive

    这个可以解决一个 when 的问题,即什么情况下会渲染对应的组件

    if/elseswitchfor 循环,都是在满足一定条件下才会渲染对应的组件

  • attribute directive

    这个则是解决了一个 how 的问题,即如何渲染对应组件

    ngModel 的双向绑定,ngClass 的添加对应类,ngStyle 的对应样式,都可以满足一个 how 的问题


http://www.ppmy.cn/news/1347926.html

相关文章

使用ESP-01/ESP-01S接入Homekit远程控制电器

一、准备材料 ESP-01/ESP-01s 芯片 、 继电器模块 、 烧录器 二、下载固件和烧录软件 固件地址https://github.com/RavenSystem/esp-homekit-devices 烧录软件下载地址&#xff1a;https://drive.google.com/file/d/1_M4EzolaJWpYXts_FwUIqH8pZWqy-fye/view 三、烧录固件 …

springboot微信小程序 uniapp学习资料分享系统v9uy4

理论意义 当今网络教学已成为各国教育改革 和发展的趋势。因此&#xff0c;构建一个适合交互式课堂教学模式的教学平台就成了当务之 急。 在国内高校&#xff0c;目前交互平台主要用于网络学院的远程教学&#xff0c;至于校园内的正规教学&#xff0c;老师自发建立课程主页的比…

横扫Spark之 - 22个常见的转换算子

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 文章目录 1. map()2. flatMap()3. filter()4. mapPartitions()5. mapPartitionsWithIndex()6. groupBy()7. distinct()8. coalesce()9. repartition()10. sortBy()11. intersection()12.union()13.…

Mac 使用AccessClient打开 windows 堡垒机的方式

使用AccessClient打开连接到 windows 页面 需要下载Microsoft remote Desktop 远程连接工具 在国内,无法下载正式版,beta 版本不需要从 app Store 下载 macOS 客户端下载地址 | Microsoft Learn 在浏览器点击对应的windows机器打开即可,会自动唤醒 Microsoft remote Desktop 进…

【算法竞赛题目 题解收集】状压DP

1. 洛谷 P 3694 P3694 P3694 邦邦的大合唱站队 传送门&#xff1a;洛谷P3694 题解&#xff1a;https://blog.csdn.net/m0_73500785/article/details/136032426?spm1001.2014.3001.5501 t a g s : tags: tags: 状压 D P DP DP 2. 学校食堂 传送门&#xff1a; 洛谷2157 题…

Nginx与history路由模式:刷新页面404问题

使用nginx部署前端项目&#xff0c;路由模式采用history模式时&#xff0c;刷新页面之后&#xff0c;显示404。 路由模式 前端路由的基本作用为&#xff1a; ①当浏览器地址变化时&#xff0c;切换页面&#xff1b; ②点击浏览器后退、前进按钮时&#xff0c;更新网页内容&…

【制作100个unity游戏之24】unity制作一个3D动物AI生态系统游戏3(附项目源码)

最终效果 文章目录 最终效果系列目录前言随着地面法线旋转在地形上随机生成动物不同部位颜色不同最终效果源码完结系列目录 前言 欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第24篇中,我们将探索如何用unity制作一…

Netty的常用组件及线程模型设计(二)

Channel、EventLoopGroup和ChannelFuture Netty网络抽象的代表: Channel–Socket EventLoop–控制流、多线程处理、并发 ChannelFuture–异步通知 Channel和EventLoop关系如图: 我们可以看出Channel需要被注册到某个EventLoop上&#xff0c;在Channel整个声明周期内部都由这个…

Python爬虫Xpath库详解#4

爬虫专栏&#xff1a;http://t.csdnimg.cn/WfCSx 前言 前面&#xff0c;我们实现了一个最基本的爬虫&#xff0c;但提取页面信息时使用的是正则表达式&#xff0c;这还是比较烦琐&#xff0c;而且万一有地方写错了&#xff0c;可能导致匹配失败&#xff0c;所以使用正则表达式…

编程中“游戏心切”心态的影响及其对策探讨

在数字化社会背景下&#xff0c;程序员作为科技领域的核心力量&#xff0c;其工作效率与专注度直接影响着项目的推进速度和质量。然而&#xff0c;在实际工作中&#xff0c;不少程序员可能会受到个人兴趣&#xff0c;如对某款游戏的强烈期待和渴望&#xff0c;导致在编程过程中…

项目02《游戏-11-开发》Unity3D

基于 项目02《游戏-10-开发》Unity3D &#xff0c; 任务&#xff1a;飞行坐骑 首先创建脚本&#xff0c; 绑定脚本&#xff0c; using UnityEngine; public class Dragon : MonoBehaviour{ [SerializeField] private float speed 10f; public Transfo…

51单片机编程应用(C语言):串口通信

目录 通信的基本概念和种类 1.1串行通信与并行通信 ​编辑 1.2同步通信与异步通信 1.3单工&#xff0c;半双工&#xff0c;全双工 1.4通信速率 二、波特率和比特率的关系 串口通信简介&#xff1a; 1.接口标准 RS-232 2、D型9针接口定义 3.通信协议&#xff1a; …

tee漏洞学习-翻译-2:探索 Qualcomm TrustZone的实现

原文&#xff1a;http://bits-please.blogspot.com/2015/08/exploring-qualcomms-trustzone.html 获取 TrustZone image 从两个不同的位置提取image 从手机设备本身从google factory image 已经root的Nexus 5设备&#xff0c;image存储在eMMC芯片上&#xff0c;并且eMMC芯片…

VSCode如何让先前打开的文件不被自动关闭,一直保持在标签栏里(关闭预览模式)

第一次接触VSCode-Huawei IDE编辑器&#xff0c;每次打开一个新的代码文件&#xff0c;旧的代码文件都会被自动关闭&#xff08;现在才知道是因为文件默认是以预览模式打开展示的&#xff09;。 那么如何才能让先前打开的文件一直保持在标签栏里呢&#xff1f; 我们需要去设置…

力扣-137. 只出现一次的数字 II

文章目录 力扣题目代码 力扣题目 给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。 示例 1&#xff1a;…

【Makefile语法 05】动静态库编译链接

目录 一、多文件项目源代码 二、静态库编译链接 三、动态库编译链接 一、多文件项目源代码 // include/add.hpp#pragma once int add(int a, int b); // include/sub.hpp#pragma once int sub(int a, int b); // src/add.cpp#include "add.hpp"int add(int a, …

office文件转pdf在线预览

一、工具类 package com.sby.utils;import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.math.RoundingMode; import java.text.DecimalFormat; import java.util.Locale;import com.aspose.cel…

Kafka系列之:Kafka集群同时设置基于时间和日志大小两种方式保存Topic的数据

Kafka系列之:Kafka集群同时设置基于时间和日志大小两种方式保存Topic的数据 一、基于日志大小二、基于时间大小三、参数设置四、设置命令一、基于日志大小 "log.retention.bytes"是Apache Kafka中的一项配置参数,用于指定每个日志段文件的最大大小。当日志段文件的…

(2024,仅高频分量的蓝噪声与高斯噪声线性插值,时变噪声)扩散模型的蓝噪声

Blue noise for diffusion models 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. 简介 2. 相关工作 3. 方法 3.1 相关噪声 3.2 具有时变噪声的扩散模型 3.3 利用矫正…

2024-02-05(Hive)

1.Hive中抽样表数据 对表进行随机抽样是非常有必要的。 大数据体系下&#xff0c;在真正的企业环境中&#xff0c;很容易出现很大的表&#xff0c;比如体积达到TB级别的。 对这种表一个简单的SELECT * 都会非常的慢&#xff0c;哪怕LIMIT 10想要看10条数据&#xff0c;也会走…
最新文章