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

相关推荐
G等你下课21 分钟前
告别刷新就丢数据!localStorage 全面指南
前端·javascript
该用户已不存在21 分钟前
不知道这些工具,难怪的你的Python开发那么慢丨Python 开发必备的6大工具
前端·后端·python
爱编程的喵24 分钟前
JavaScript闭包实战:从类封装到防抖函数的深度解析
前端·javascript
LovelyAqaurius24 分钟前
Unity URP管线着色器库攻略part1
前端
Xy91027 分钟前
开发者视角:App Trace 一键拉起(Deep Linking)技术详解
java·前端·后端
lalalalalalalala30 分钟前
开箱即用的 Vue3 无限平滑滚动组件
前端·vue.js
前端Hardy30 分钟前
8个你必须掌握的「Vue」实用技巧
前端·javascript·vue.js
嘻嘻哈哈开森32 分钟前
技术分享:深入了解 PlantUML
后端·面试·架构
snakeshe101032 分钟前
深入理解 React 中 useEffect 的 cleanUp 机制
前端
星月日33 分钟前
深拷贝还在用lodash吗?来试试原装的structuredClone()吧!
前端·javascript