Angular 17 信号 Signals

一、简介

Angular Signals是一个系统,可以精细地跟踪整个应用程序中状态的使用方式和位置,从而使框架能够优化渲染更新。

信号 Signals 早已经不是新的概念了。在 PReact 和 solidjs 中早已经有了有了实践。

二、初始化项目

sh 复制代码
npm install -g @angular/cli

ng new my-app
cd my-app
ng serve --open

三、定义 Signals

  • HTML UI
html 复制代码
<div style="font-size: 80px;">{{count()}}</div>
<div (click)="set()">设置</div>
<div (click)="add()">字体 +1</div>
<div (click)="del()">字体 -1</div>
  • TS 设置和更新 逻辑
ts 复制代码
import { Component, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  count = signal(1)
   // 设置大小
  set() { 
    this.count.set(123)
  }
  // 增加
  add() {
    this.count.update(c => c + 1)
  }
  // 减小
  del() {
    this.count.update(c => c - 1)
  }
}

四、计算 computed Singal

计算 Singal 不是可写的

  • html
html 复制代码
<p>compouted works!</p>
<div>{{ count() }}</div>
<div>{{ countPlus() }}</div>
<button (click)="add()">+1</button>
  • TS 计算属性逻辑
ts 复制代码
import { Component, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-compouted',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './compouted.component.html',
  styleUrl: './compouted.component.css'
})
export class CompoutedComponent {
  count = signal(2)

  countPlus = computed(() => { return this.count() * this.count() })

  add() {
    this.count.update(() => this.count() * this.count())
  }

五、条件计算:动通过 computed 计算

ts 复制代码
const showCount = signal(false);
const count = signal(0);
const conditionalCount = computed(() => {
  if (showCount()) {
    return `The count is ${count()}.`;
  } else {
    return 'Nothing to see here!';
  }
});

六、effect 副作用

ts 复制代码
import { Component, computed, signal, effect } from '@angular/core';
import { CommonModule } from '@angular/common';
import { count } from 'rxjs';

@Component({
  selector: 'app-effect',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './effect.component.html',
  styleUrl: './effect.component.css',
})
export class EffectComponent {
  count = signal(12);
  countPlus = computed(() => this.count() * this.count());

  countEff = effect(() => {
    console.log(
      `The current count is: ${this.count()} and ${this.countPlus()}`
    );
  });
}

需要注意的是 effect 函数需要一个返回值,

七、onCleanup 清理(定时器)

ts 复制代码
effect((onCleanup) => {
  const user = currentUser();
  const timer = setTimeout(() => {
    console.log(`1 second ago, the user became ${user}`);
  }, 1000);
  onCleanup(() => {
    clearTimeout(timer);
  });
});

八、rxjs 可观察对象转信号

Angular 的@angular/core/rxjs-interop包提供了有用的实用程序来将Angular Signals与 RxJS Observables 集成。

  • html
html 复制代码
<p>rxjs works!</p>
<div>{{counter()}}</div>
  • TS 逻辑
ts 复制代码
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { interval } from 'rxjs';
import { toSignal} from '@angular/core/rxjs-interop'
@Component({
  selector: 'app-rxjs',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './rxjs.component.html',
  styleUrl: './rxjs.component.css'
})
export class RxjsComponent {
   counterObservable = interval(1000);
  // Get a `Signal` representing the `counterObservable`'s value.
  counter = toSignal(this.counterObservable, {initialValue: 0});
}

九、rxjs 信号转可观察对象

ts 复制代码
import { Component, signal, effect } from '@angular/core';
import { CommonModule } from '@angular/common';
import { interval } from 'rxjs';
import { toSignal, toObservable } from '@angular/core/rxjs-interop'
@Component({
  selector: 'app-rxjs',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './rxjs.component.html',
  styleUrl: './rxjs.component.css'
})
export class RxjsComponent {
  counterObservable = interval(1000);
  // Get a `Signal` representing the `counterObservable`'s value.
  counter = toSignal(this.counterObservable, {initialValue: 0});


  num = signal(100)
  num$ = toObservable(this.num)
  numEff = effect(() => {
    this.num$.subscribe({
      next(v) {
        console.log(v)
      }
    })
  })
}

十、小结

本文主要关注 Angular 17 汇总关于信号的内容,使用 signal 函数传入值定义一个信号数据。使用 set 方法进行设置,使用 update 方法进行更新。当然 signal 支持计算方法,通过 computed 计算出一个新的值,或者依据其他的 signal 计算一个新的值。同时 angular 支持 effect 函数,用于处理副作用,你的定时器都可以通过 effect 的 onCleanup 方法进行清除。因为 Angular 支持 RxJS 信号也对可观察对象进行了支持,可以通过可观察对象对其进行相互转换。

相关推荐
想用offer打牌7 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
崔庆才丨静觅8 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
KYGALYX9 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅9 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法10 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
崔庆才丨静觅10 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment10 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端