Angular 16 Signal更新不更新视图

kkl*_*zek 4 signals zonejs angular angular16

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

主要.ts

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

应用程序组件.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 + "!!");
    }
}
Run Code Online (Sandbox Code Playgroud)

我期望单击按钮后,“标题”的值将从“Hello”更新为“Hello!!”。它没有更新。

Dub*_*ubl 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 变更检测过程中的作用(它仍然非常相关)。