阅读列表

关于Angular Signal - 我非常理解你的愤怒

本文介绍了Angular Signal的应用场合。

Oceanic

发表于 2025年04月01日

加入到阅读列表分享本文到 X

前些日子我在reddit上看到一个哥们提了一个关于Angular Signal的问题,大意是“我看了那个关于counter的signal的例子,也知道set和computed的一切,但是我就是不明白signal到底是干什么用的”。看到这个问题我会心一笑,因为这完全就是我的想法。在Angular推出了那个绚烂的新网站的那段日子,大街上的每个人都在谈论着signal,仿佛他们早就知道这一切,似乎signal是所有编程语言都有的功能,唯独Angular没有,而现在终于有了,大家弹冠相庆。那段日子我感觉自己被孤立,于是花了很多时间去看各种Angular Signal的文章,而这些文章大部分还是在重复那个counter的例子,如果你已经对那个糟糕的文档感到厌倦,我非常理解你的愤怒。所以我现在要把我了解到的Angular Signal介绍给你,毕竟我们是同道中人,我们都是从counter例子起步,开始寻找正确的方向。

首先让我把真正的困惑拿到桌面上:如果你像我一样关心用户的感受,你一定会有一种意识:some_var 和 some_var() 是两个完全不同的东西,在大多数编程语言中,带有括号意味着这是一个函数,函数意味着它将比一个变量产生更大的开销。所以当你看到有人不用 counter = 0; total = counter + 100; 而是非要用函数去干这个事情的时候,就会觉得很奇怪。

但是以现在Signal的火爆程度,你会从心里意识到这个东西是有意义的,你不得不使用它,否则你的代码会在未来某个时刻被淘汰掉,而事实也正是如此。下面我将介绍都应该在什么时候使用Signal,以及为什么这么做。

规则1:当你的模板中使用了某个组件变量,并且该变量会改变时,你要使用Signal

<p>{{title}}<p>
@if(loading){
	<p>Loading, please wait...</p>
} @else {
	<p>Items from book {{bookName}}</p>:
	@for(item of items; track $index){
		<p>{{item.id}} - {{item.name}}</p>
	}
}

上面是一个常见的模板,组件加载后会设置一个title,然后使用http get从服务器获取数据,在做这些事情之前设置了一个loading状态,然后获取数据后显示在模版中:

title : string = 'My Book Store';
loading : boolean = false;
bookName : string = '';
items : Items[] = [];

ngOnInit() : void{
	this.loadBookById(0);
}

onButtonLoadBook_123() : void{
	this.loadBookById(123);
}

onButtonLoadBook_456() : void{
	this.loadBookById(456);
}

private loadBookById(id : number) : void{
	this.loading = true;
	this.http_get(id).subscribe({next : (data) => {
		this.bookName = data.bookName;
		this.items = data.items;
		this.loading = false;
	}});
}

这段代码运行的一直很正常,但是你一定看到过这种标题的文章:“xxx tips to xxx your Angular Application Performance in year xxxx”:

其中必有“Tip n: 使用 ChangeDetectionStrategy.OnPush”:

@Component({
  selector: 'app-my-component',
  changeDetection: ChangeDetectionStrategy.OnPush,
  templateUrl: ...
})

我觉得很奇怪:如果OnPush这么好为什么Angular不直接默认使用OnPush?当我把那行ChangeDetectionStrategy代码加入到@Component里,我就知道为什么了:某些状态的更新了但是模板不去显示新的结果。我想如果你关心最近Angular的发展你应该已经知道了前因后果:Angular正在准备废除掉zone.js,而OnPush更新检测就是代替zone.js的新手段,前提是你需要把所有模版里会在运行时改变的值改用signal:

这是一篇需要付费阅读的文章,请完成支付以阅读完整的文章