找回密码
 立即注册
首页 业界区 业界 Angular 18+ 高级教程 – Component 组件 の @let Templ ...

Angular 18+ 高级教程 – Component 组件 の @let Template Local Variables

府扔影 4 天前
前言

Angular 在 v18.1 推出了 Template 新语法 @let。
这个 @let 和上一篇教的 Control Flow @if, @for, @swtich, @defer 语法上类似,但是用途却差很多。
如果要给它们分类的话,@if @for @switch 可以算一类,@defer 独立一类,@let 又是独立一类,总之大家不要混淆就是了。
 
没有 @let 的日子

我们先来看看没有 @let 的日子里,我们都遇到了哪些不方便。
Long path access

App 组件
  1. export class AppComponent {
  2.   person = signal({
  3.     name: 'Derrick',
  4.     address: {
  5.       country: 'Malaysia',
  6.       state: 'Johor',
  7.       postalCode: '81300'
  8.     }
  9.   })
  10. }
复制代码
有一个 person 对象,它里面又有一个 address 对象。
App Template
  1. <p>{{ person().name }}</p>
  2. <p>{{ person().address.country }}</p>
  3. <p>{{ person().address.state }}</p>
  4. <p>{{ person().address.postalCode }}</p>
复制代码
上述代码最大的问题就是 person().address 一直重复,代码很长,很丑。
倘若在 JS 里的话,我们一定会 declare 一个 variable 把 address 对象装起来,像这样访问
  1. const address = person.address;
  2. console.log(address.country);
  3. console.log(address.state);
  4. console.log(address.postalCode);
复制代码
没有一直重复 person.address 干净多了。
但是在 Template 里,我们无法 declare variable,能 declare variable 的只有组件
  1. export class AppComponent {
  2.   person = signal({
  3.     name: 'Derrick',
  4.     address: {
  5.       country: 'Malaysia',
  6.       state: 'Johor',
  7.       postalCode: '81300'
  8.     }
  9.   });
  10.   address = computed(() => this.person().address);
  11. }
复制代码
App Template
  1. <p>{{ person().name }}</p>
  2. <p>{{ address().country }}</p>
  3. <p>{{ address().state }}</p>
  4. <p>{{ address().postalCode }}</p>
复制代码
虽然 path 是短了,但是组件却为了 View 而多了一个 property,这样的职责分配合理吗?
再说,如果是在 @for 里面
  1. @for (person of people(); track person.name) {
  2.   <p>{{ person.name }}</p>
  3.   <p>{{ person.address.country }}</p>
  4.   <p>{{ person.address.state }}</p>
  5.   <p>{{ person.address.postalCode }}</p>
  6. }
复制代码
组件 property 也无法解决这个问题丫。
the hacking way

有些人会用 hacking way 来做到这一点,像这样
  1. @for (person of people(); track person.name) {
  2.   <p>{{ person.name }}</p>
  3.   @if (person.address; as address) {
  4.     <p>{{ address.country }}</p>
  5.     <p>{{ address.state }}</p>
  6.     <p>{{ address.postalCode }}</p>
  7.   }
  8. }
复制代码
虽然 path 是短了,但是 @if 是这样用的吗?这种不顺风水的用法,随时会掉坑里的,忌讳啊。
Async pipe

App 组件
  1. export class AppComponent {
  2.   value$ = of('hello world');
  3. }
复制代码
有一个 value stream。
App Template
  1. <header>
  2.   <p>{{ value$ | async }}</p>
  3. </header>
  4. <main>
  5.   <p>body</p>
  6. </main>
  7. <footer>
  8.   <p>{{ value$ | async }}</p>
  9. </footer>
复制代码
我要在 header 和 footer 显示这个 value。
上述代码有两个问题:

  • 两次 pipe async 会导致 value stream 被 subscribe 两次。
    如果这个 value 需要发 ajax,那它就会发 2 次 ajax。
  • 不管是使用什么 pipe 都好,每一次使用 value 都要重复同样的 pipe,这就不合理。
    而,倘若我们把职责交给组件,那组件就需要使用 pipe,这样也不合理。
    总之,怎样都不合理,这就是一个设计失误。
总结

Angular 对 Template 限制太多了,以至于许多简单的 View 逻辑无法在 Template 里完成,必须转交给不合适的组件,或者大费周章的指令去完成。
这也是为什么这个 issue 能常年霸榜
1.png


幸好,在经历了 2657 个日夜
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册