首页  >  文章  >  web前端  >  Angular @let 声明:智能模板订阅

Angular @let 声明:智能模板订阅

PHPz
PHPz原创
2024-09-03 14:37:071097浏览

一段时间以来,Angular 一直保持着强劲的势头,Angular 团队也证明了它对社区的关心。在 Angular v17 和随后的小版本中,Angular 团队提供了许多出色的功能,其中最突出的功能是新的内置 block 模板语法,即使在开发者预览版中也是如此,它简化了使用模板。

在最近的版本中,Angular 存储库中两个期待已久的问题已得到解决。 Angular 主要版本 v18 提供了统一控制状态更改事件以及其他功能,次要版本 v18.1 通过向模板添加新的内置功能来利用 block 模板语法称为模板局部变量,用@let块表示。

查看官方博客文章,了解更多关于 @let 变量如何定义、工作、限制以及它们如何更新其值的信息。

简单来说,模板局部变量,允许 Angular 开发人员在模板中声明变量,就像我们在组件的类中所做的那样,简化了我们在模板中编写逻辑的方式,从而为某些旧的模板模式,并引入 @eneajaho 的本文中介绍的新用例。

本文的动机来自 Reddit 帖子,询问是否需要 @let 声明以及为什么应该使用它们。

您可以在此处找到主要 Angular 贡献者 Matthieu Riegler 关于此主题的观点。

在本文中,我想展示这些本地模板变量的用例我发现在我从事的项目中很有用,我不再需要使用 RxJS 进行“缓存”shareReplay 运算符,用于在不同模板部分中使用相同的数据。

让我们深入了解一下?.


RxJS 使用 shareReplay 运算符进行“缓存”

在开发 Web 应用程序时,开发人员最常见的事情就是发出 HTTP 请求。在 Angular 中,HTTP 通信是通过基于可观察的 API 完成的,即流行的

HttpClient。由于在大多数情况下,获取的数据都绑定在模板中,因此开发人员遵循声明式方法,将 Async 管道作为最佳实践 - 自动订阅模板中的可观察对象,并在组件被销毁时取消订阅? :

...
@Component({
  ...
  template: `
    ...
    <main>
      ...            ?
      @if (todo$ | async; as todo) {
        <p>Title: {{todo.title}}</p>
      }
    </main>
   ...
  `,
  standalone: true,
  ...
})
export class ShareReplayComponent {
  todo$ = inject(HttpClient)
    .get<Todo>('https://jsonplaceholder.typicode.com/todos/1');
}
但是有些情况下,我们需要模板中其他位置的同一流中的数据,因此我们再次将模板中的可观察流与

Async 管道绑定 ?:

...
@Component({
  template: `
    ...
    <main>
      ...           ?
      @if (todo$ | async; as todo) {
        <p>Title: {{todo.title}}</p>
      }
    </main>

    <aside>
      ...            ?
      @if (todo$ | async; as todo) {
        <p>Is Completed: {{todo.completed}}</p>
      }
    </aside>
   ...    
  `,
  standalone: true,
})
export class ShareReplayComponent {
  todo$ = inject(HttpClient)
    .get<Todo>('https://jsonplaceholder.typicode.com/todos/1');
}
这会导致相同的可观察流在模板的两个不同部分中绑定和订阅,从而有两个重复的 HTTP 请求正在进行,以不必要地获取相同的数据?:

Angular @let declarations: Smart Template Subscriptions

这种情况的常见解决方案(我见过)是通过

shareReplay 运算符使用 RxJS 缓存第一个触发的 HTTP 请求的数据:

...
@Component({
  template: `
    ...
    <main>
      ...            ?
      @if (todo$ | async; as todo) {
        <p>Title: {{todo.title}}</p>
      }
    </main>

    <aside>
      ...            ?
      @if (todo$ | async; as todo) {
        <p>Is Completed: {{todo.completed}}</p>
      }
    </aside>
   ...
  `,
  standalone: true,

})
export class ShareReplayComponent {
  todo$ = inject(HttpClient)
    .get<Todo>('https://jsonplaceholder.typicode.com/todos/1')
    .pipe(shareReplay(1)); ?
}
这确保即使在模板中的多个位置使用

Async 管道绑定和订阅相同的可观察流,也只会触发一个 HTTP 请求,并且响应数据会被缓存 ?:

Angular @let declarations: Smart Template Subscriptions

这个模式工作得很好,但是我们可以更简单地实现这个功能吗?

让我们来看看?.

用于简化的 @let 声明

虽然 RxJS 解决方案运行良好并满足我们的需求,但 Angular v18.1 中引入的

@let 声明提供了一种更简单、基于模板的替代方案 ?:

...
@Component({
  template: `
    ...
    @let todo = todo$ | async; ?
    <main>
      ...
      @if (todo) {
        <p>Title: {{todo.title}}</p>
      }
    </main>

    <aside>
      ...
      @if (todo) {
        <p>Is Completed: {{todo.completed}}</p>
      }
    </aside>
   ...
  `,
  standalone: true,

})
export class LetVariablesComponent {
  todo$ = inject(HttpClient)
    .get<Todo>('https://jsonplaceholder.typicode.com/todos/1');
}
可以注意到,它提供了一种“基于模板的缓存”——绑定并订阅在模板中仅可观察一次的 HTTP 请求 ?:

Angular @let declarations: Smart Template Subscriptions

因此,不会传出重复的 HTTP 请求,并且不需要通过

shareReplay 运算符进行 RxJS 缓存。 ??

注意?:此解决方案在缓存模板数据时有效。如果组件的类中需要缓存数据,则需要

shareReplay 运算符。


特别感谢@kreuzerk 和@eneajaho 的审阅。

感谢您的阅读!

我希望你喜欢它?如果您喜欢这篇文章,请与您的朋友和同事分享。

如有任何问题或建议,请随时在下面评论?.

如果这篇文章对您来说有趣且有用,并且您不想错过以后的文章,请通过 @lilbeqiri、dev.to 或 Medium 关注我。 ?

以上是Angular @let 声明:智能模板订阅的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn