Angular 16 信号更新不更新视图

问题描述 投票:0回答:1

我正在测试 Angular 16 信号,根据我的理解,当我禁用 zone.js 并调用 signal.update() 时,视图应该更新为新值。它不是。请帮助我理解为什么。

main.ts

platformBrowserDynamic().bootstrapModule(AppModule, { ngZone: 'noop' })
    .catch(err => console.error(err));

app.component.ts

@Component({
    selector: 'app-root',
    template: '
        <h1>{{ title() }}</h1>
        <button (click)="click()">Change</button>
    ',
})
export class AppComponent {
    title = signal('Hello');

    click(): void {
        this.title.update((value) => value + "!!");
    }
}

我期望单击按钮后,“title”的值将从“Hello”更新为“Hello!!”。还没更新。

angular signals zonejs angular16
1个回答
8
投票

TL;DR:因为 Angular 仍然使用 zone.js 来触发更改检测。

Zone.js 在幕后包装了一堆浏览器 API,以便检测页面上何时发生事件(它会查找特定类型的事件,请参阅有关区域的 Angular 文档了解更多详细信息)。它不会通知 Angular 到底发生了什么事件,但它会说某处的某些值可能已更改。然后,Angular 启动更改检测,循环遍历整个组件树,检查所有组件是否有更改。如果启用

ChangeDetectionStrategy.OnPush
,那么它会更高效,只检查树中可能已更改的组件。

这就是为什么您会看到函数执行以正确更新信号。缺少的链接是 zone.js 会检测到这一点并通知 Angular 某些内容已更新,以便启动更改检测。如果您要添加一个调用来手动触发更改检测,那么它应该会让您的示例再次工作。

信号只是从兼容应用程序中完全删除 zone.js 的第一步。 Angular 的 GitHub 存储库上有一个(现已完成)RFC,讨论了基于信号的组件,这将是朝着实现无区域 Angular 应用程序迈出的又一步。改变 Angular 的所有基础设施只需要一些时间,因为 zone.js 是 Angular 目前工作方式的基本组成部分。

这是一篇有点旧的文章,其中讨论了更多 zone.js 及其在 Angular 变更检测过程中的作用(它仍然非常相关)。

更新(2024-04-15):这个答案也得到了 2024 年 NG-Conf 主题演讲内容的支持。他们谈论了新的信号 API,这是朝这个方向迈出的又一大步(具体来说,信号输入信号查询和模型输入以及新的输出 API)。当他们说完这个之后,他们对删除 JS 区域有这样的说法:

嗯,在我们开始建议人们完全无区域之前,我们仍然需要做出一些改进。使用新的信号 API 是准备将区域移出应用程序的一个巨大飞跃,您知道还有其他好处,但我们仍然需要做一些工作来确保体验像我们一样简化。我喜欢。特别是,框架如何安排任务,以及如何与测试中的变更检测交互。

但我们正在朝着这一目标取得重大进展。我们将拥有一条光线充足的路径,用于通过信号完全驱动 UI 更新。

这是视频相关部分的链接。

© www.soinside.com 2019 - 2024. All rights reserved.