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

相关推荐
橙子家1 小时前
浏览器缓存之【基础键值存储】:Local storage 和 Session storage
前端
星星在线3 小时前
MusicFree:一个「All in One」的个人音乐服务器,让听歌回归简单
前端·后端
IT_陈寒4 小时前
Redis的SETNX并发问题让我加了三天班
前端·人工智能·后端
demo007x4 小时前
Docling 文档转换以及技术架构分析
前端·后端·程序员
京东云开发者5 小时前
京东市民服务又“上新”!这次是黑龙江“龙易办”
前端
袋鱼不重6 小时前
我的神奇同事,AI 用多了居然写了个 Open In Codex
前端·后端·ai编程
用户8356290780516 小时前
使用 Python 操作 Word 内容控件
后端·python
像我这样帅的人丶你还6 小时前
啥? 前端也要会干Java?🛵🛵🛵
后端
Hommy886 小时前
【剪映小助手】添加贴纸接口(Add Sticker)
后端·github·剪映小助手·视频剪辑自动化·剪映api
Fireworks6 小时前
深入vue3源码解读 -- 1、响应式的基础概念
前端