Angular 17+ 高级教程 – Component 组件 の Control Flow

这篇具有很好参考价值的文章主要介绍了Angular 17+ 高级教程 – Component 组件 の Control Flow。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 

前言

Control Flow 是 Angular v17 版本后推出的新模板语法,用来取代 NgIf、NgForOf、NgSwitch 这 3 个 Structure Directive。

Structure Directive 的好处是比较灵活,原理简单,但是即便用了微语法,它看上去还是相当繁琐,而且不够优雅。

Conrol Flow 的好处是它的语法够美,缺点是不必 Structure Directive 灵活,开发者无法做任何 customize,只能看 Angular 给什么用什么。

 

参考

Docs – Built-in control flow

Docs – Deferrable Views

 

@if @else if @else

这个是 NgIf 指令的写法

<ng-template #loadingTemplate>
  <p>loading...</p>
</ng-template>

<p *ngIf="person$ | async as person; else loadingTemplate">{{ person.name }}</p>

这个是 Control Flow 的写法

@if(person$ | async; as person) {
  <p>{{ person.name }}</p>
}
@else {
  <p>loading...</p>
}

Control Flow 还支持 @else if,这个是 NgIf 指令不支持的。

@if (value >= 5) {
  <p>greater than or equal to five</p>
}
@else if (value >= 2) {
  <p>greater than or equal to two</p>
}
@else {
  <p>less than two</p>
}

Control Flow @if 的原理

Contorl Flow 不依赖 NgIf 指令,甚至不依赖 ViewContainerRef,它使用的是比较底层的接口,

比如 createAndRenderEmbeddedLView 函数和 addLViewToLContainer 函数。这两个函数的源码我们在 Dynamic Component 文章中研究过,

它们也是 ViewContainerRef 内部使用的。

app.component.js

Angular 17+ 高级教程 – Component 组件 の Control Flow

在 renderView 阶段,@if、@else if、@else 分别会创建三个 ng-template。

在 refreshView 阶段,会执行 ɵɵconditional 函数。第二个参数依据判断条件它会宣传第几个 ng-template。

ɵɵconditional 函数的源码在 control_flow.ts

Angular 17+ 高级教程 – Component 组件 の Control Flow

 

@for @empty

这个是 NgForOf 指令的写法

<ng-template #noDataTemplate>
  <p>no datas</p>
</ng-template>

<ng-container *ngIf="people.length > 0 else noDataTemplate">
  <ng-container *ngFor="let person of people; trackBy: trackByName; let index = index">
    <p>index: {{ index }}</p>
    <p>name : {{ person.name }}</p>
  </ng-container>
</ng-container>

这个是 Control Flow 的写法

@for (person of people; track person.name; let index = $index) {
  <p>index: {{ index }}</p>
  <p>name : {{ person.name }}</p>
} 
@empty {
  <p>no datas</p>
}

有 2 个点非常强

  1. trackByFunction 不需要在 AppComponent 里定义了

  2. @empty 取代了 NgIf 指令

@for 的原理我们就不翻源码了,它和 @if 一样都不依赖 Structure Directive,里面都是调用底层的接口,也因为这样 @for 比 NgForOf 指令速度快很多哦。

 

@switch @case @default

这个是 NgSwitch 指令的写法

<ng-container [ngSwitch]="status">

  <ng-template [ngSwitchCase]="'Completed'">
    <p>complete</p>
  </ng-template>

  <ng-template [ngSwitchCase]="'Pending'">
    <p>pending</p>
  </ng-template>
  
  <ng-template ngSwitchDefault>
    <p>none</p>
  </ng-template>

</ng-container>

这个是 Control Flow 的写法

@switch (status) 
{
  @case ('Completed') {
    <p>complete</p>
  }
  @case ('Pending') {
    <p>pending</p>
  }
  @default {
    <p>none</p>
  }
}

提醒:@switch 和 ngSwtich 指令一样,都没有 fallthrough 的概念,match 到后会自动 break。

 

@defer @placeholder @loading @error

@defer 是 Control Flow 独有的,不存在 Defer 指令。

@defer 的作用是延迟显示一段内容,并且内容里包含的组件/指令/Pipe 还会延迟加载。

@defer (on timer(5s)) {
  <app-say-hi />
  <app-hello-world />
}

上面这段表示 5 秒中后才输出 SayHi 和 HelloWorld 组件。

我们可以这样去理解,@defer 会被 compile 成 ng-template,5 秒钟后会 createEmbeddedView 然后 insert。

此外 compile 时它还会找出涉及的组件,改成使用 import('/path/component.ts') 的方式动态加载,这样可以减少 first load 的 bundle size。

app.component.js

Angular 17+ 高级教程 – Component 组件 の Control Flow

@loading,@placeholder,@error

@defer (on timer(2s)) {
  <app-say-hi />
  <app-hello-world />
}
@placeholder {
  <p>blank...</p>
}
@loading {
  <p>loading...</p>
}
@error {
  <p>something wrong</p>
}

@defer 的显示流程是这样:

一开始先显示 @placeholder 的内容,等 on timer 触发后,显示 @loading 内容,这时会去 lazyload -> createEmbededView -> insert,最终显示 @defer 内容。

如果 lazyload 的过程失败,那就显示 @error 内容。

minimum 和 after options

有时候 lazyload 或许会太快,loading 一闪而过体验不好,这时可以设置 after 和 minimum。

@loading(after 100ms; minimum 1s) {
  <p>loading...</p>
}

当开始 lazyload 后,Angular 会开始计时,超过 100ms 后,如果 lazyload 还没有结束,那就会显示 @loading 内容,

如果 lazyload 在 1 秒钟内完成,它不会马上输出 @defer 内容,而是会等到 minimum 1s 后才输出。

注:after 和 minimum 是同时开始计时的。

@placeholder 也支持 minimum options,不过不支持 after 哦。

Trigger

除了 on timer 以外,还有另外 5 个 Triggers。

  1. @defer (on idle)

    idle 指的是游览器的 requestIdleCallback 事件

  2. @defer (on immediate)

    immediate 表示一旦 Angular first render 结束后立马就触发。

  3. @defer (on timer(500ms))

    timer 就是 setTimeout,可以写 ms (millisecond) 或者 s (second)

  4. @defer (on hover)

    <div #hoverArea>hover area</div>
    @defer (on hover(hoverArea)) {
      <app-say-hi />
      <app-hello-world />
    }
    
    @defer(on hover) {
      <app-say-hi />
      <app-hello-world />
    }
    @placeholder {
      <div>hover area</div>
    }

    hover element 默认是 @placeholder 内容,我们可以传入 element 作为指定的 hover area。

  5. @defer(on viewport)

    viewport 指的是当指定的 element 出现在 viewport 里,它是通过 IntersectionObserver 实现的。

    和 on hover 一样,默认的 element 是 @placeholder,我们可以通过传入参数指定 element。

  6. @defer (on interaction)

    interaction 指的是 click 和 keydown 事件,和 on hover / on viewport 一样可以指定 element。

我们可以写 multiple trigger,它的关系是 "or",也就是说只要其中一个 trigger 触发就执行。

@defer (on viewport; on timer(5s)) {
  <app-say-hi />
  <app-hello-world />
}

当 on viewport 或者超过 5 秒后显示。

Prefetching

prefetching 的作用是多一个 trigger 用于是否提早 lazyload。

@defer (on viewport; prefetch on timer(5s)) {
  <app-say-hi />
  <app-hello-world />
}
@placeholder {
  <p>placeholder</p>
}

5 秒后,虽然 element 没有 on viewport 但会先去加载,只加载不显示,一直到 element on viewport 才显示。

prefetch 也可以写 multiple trigger,只要其中一个触发就执行

@defer (on viewport; on timer(5s); prefetch on timer(3s); prefetch on hover) {
  <app-say-hi />
  <app-hello-world />
}
@placeholder {
  <p>placeholder</p>
}

 

总结

Control Flow 代码比起 Structure Directive + 微语法整齐很多,代价是无法扩展。

NgIf、NgForOf、NgSwtich 指令相信在不久的将来会被淘汰,但是 ng-template、Structure Directive 和微语法是不会被淘汰的,

而要掌握好 Structure Directive 和微语法,我个人觉得 NgIf、NgForOf、NgSwtich 指令是非常值得参考的。

 

目录

上一篇 Angular 17+ 高级教程 – Component 组件 の Structural Directive (结构型指令) & Syntax Reference (微语法)

下一篇 Angular 17+ 高级教程 – NgModule

想查看目录,请移步 Angular 17+ 高级教程 – 目录文章来源地址https://www.toymoban.com/news/detail-838534.html

到了这里,关于Angular 17+ 高级教程 – Component 组件 の Control Flow的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Angular 17+ 高级教程 – Component 组件 の Structural Directive (结构型指令) & Syntax Reference (微语法)

    在 Attribute Directives 属性型指令 文章中,我们学习过了指令。指令是没有 HTML 和 CSS 的组件,它单纯用于封装 JS 的部分。 这一篇我们将继续学习另一种指令 -- Structural Directive 结构型指令。 就代码而言,Structural Directive 和 Attribute Directives 是完全一样的,只是用途不同,因此

    2024年03月10日
    浏览(38)
  • Angular 17+ 高级教程 – Library

    当你需要管理超过一个项目时,你就需要知道怎么使用 Angular Library。 你可以把多个项目共享的组件放到这个 Library 了,就像 Angular Material 那样。   Sandro Roth – Building an Angular Library with multiple entry points (主要参考) Docs – Creating libraries Docs – Copy assets Docs – Embed assets in C

    2024年04月17日
    浏览(27)
  • Angular 17+ 高级教程 – Signals

    在上一篇 Change Detection 中, 我们有提到 MVVM 监听 ViewModel 变化的难题. 当年 AngularJS 和 Knockout.js (下面简称 KO) 各自选了不同的道路. 但如今, 事过境迁, Angular 最终也走向了 KO 的道路. 这就是这篇的主角 Signal。   在 JavaScript, 值类型 variable 无法被监听, Signal 的做法是把它们都变

    2024年03月09日
    浏览(57)
  • Angular 17+ 高级教程 – HttpClient

    HttpClient 是 Angular 对 XMLHttpRequest 和 Fetch 的封装。 HttpClient 的 DX (Developer Experience) 比 XMLHttpRequest 和 Fetch 都好,只是学习成本比较高,因为它融入了 RxJS 概念。 要深入理解 HttpClient 最好先掌握 3 个基础技能: XMLHttpRequest -- 看这篇 Fetch -- 看这篇 RxJS -- 看这系列 (如果只是为了

    2024年03月16日
    浏览(41)
  • Angular 17+ 高级教程 – NgModule

    NgModule 在 Angular v14 以前是一门必修课。然而,自 Angular v14 推出 Standalone Component 以后,它的地位变得越来越边缘化了。 本教程从开篇到本篇,所有例子使用的都是 Standalone Component,一点 NgModule 的影子也没有😔。 但是!NgModule 还是有价值的,而且在越复杂的项目中你越可以

    2024年03月12日
    浏览(52)
  • Angular 17+ 高级教程 – 盘点 Angular v14 到 v17 的重大改变

    我在 初识 Angular 文章里有提到 Angular 目前的断层问题。 大部分的 Angular 用户都停留在 v9.0 版本。 v9.0 是一个里程碑版本,Angular 从 v4.0 稳定版推出后,好几年都没有什么动静,直到 v9.0 推出了 Ivy rendering engine。 本以为 v9.0 以后 Angular 会大爆发,结果迎来的是 Angular 团队搞内

    2024年04月22日
    浏览(24)
  • Angular 17+ 高级教程 – Change Detection

    虽然 Angular 正在把大部分 Change Detection 概念换成 Signal,但是最快也要 1 年后,所以还是有必要认真学习一下的。   MVVM 框架的开发方式是这样的: 写 HTML 写 ViewModel 在 HTML 里加入 binding syntax。 在 HTML 里加入 listening syntax,在事件发生时修改 ViewModel。 MVVM 的宗旨是 \\\"不要直接

    2024年03月09日
    浏览(30)
  • Angular 17+ 高级教程 – 学以致用

    读这么多原理,到底为了什么?真实项目中真的会用得到吗? 你正在疑惑 \\\"知识的力量\\\" 吗? 本篇会给一个非常非常好的案例,让你感悟 -- 知识如何用于实战。 记住,我的目的是让你感悟,而不是要你盲目相信知识。   下面是我在 2020-11-06 记入的一个问题。 一模一样的问题

    2024年04月22日
    浏览(25)
  • Angular 17+ 高级教程 – Angular 的局限 の Query Elements

    熟悉 Angular 的朋友都知道,Angular 有非常多的局限,许多事情它都做不好,打开 Github 一堆 2016 - 2017 的 Issues,时至今日都没有解决。 原因也很简单 -- Angular 团队的不作为😔。 通常我会把常见的 Angular 的局限记入在这篇 Angular 的局限和 Github Issues,但由于本篇要讲的问题篇幅

    2024年04月24日
    浏览(28)
  • Angular 17+ 高级教程 – Dependency Injection 依赖注入

    本来是想先介绍 Angular Component 的,但 Component 里面会涉及到一些 Dependency Injection (简称 DI) 的概念,所以还是先介绍 DI 吧。 温馨提醒:如果你对 JS class、prototype 不太熟悉的话,建议你先看这篇 JavaScript – 理解 Object, Class, This, Prototype, Function, Mixins   首先我们有一个 class Ser

    2024年03月09日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包