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 信号也对可观察对象进行了支持,可以通过可观察对象对其进行相互转换。

相关推荐
仰泳之鹅3 分钟前
【杂谈】C语言中的链接属性、声明周期以及static关键字
java·c语言·前端
空空kkk5 分钟前
Spring Boot项目的搭建
java·spring boot·后端
2501_940315266 分钟前
【无标题】(leetcode933)最近的请求次数
java·前端·javascript
张丶大帅8 分钟前
【走进Golang】
开发语言·后端·golang
每天学习一丢丢10 分钟前
Spring Boot 调用泛微 E9 Token 认证 + 创建流程完整教程
java·spring boot·后端
wb0430720111 分钟前
一次jvm配置问题导致的数据库连接异常
服务器·jvm·数据库·后端
楼田莉子11 分钟前
CMake学习:入门及其下载配置
开发语言·c++·vscode·后端·学习
智源研究院官方账号14 分钟前
技术详解 | 众智FlagOS1.6:一套系统,打通多框架与多芯片上下适配
人工智能·驱动开发·后端·架构·硬件架构·硬件工程·harmonyos
invicinble14 分钟前
对于进行报表的经验思考
后端
没有bug.的程序员15 分钟前
Spring Boot 启动原理:从 @SpringBootApplication 到自动配置深度解析
java·spring boot·后端·python·springboot·application