关于 angular-zoneless
面向 Angular 开发者的无 Zone 变更检测实践指南,介绍 Angular 19+ 中启用 zoneless 模式及配套 API 的用法。内容涵盖 Signals、渲染回调、异步处理和测试。
主要功能
- 01启用无 Zone 变更检测
- 02使用 signal() 与 computed()
- 03通过 afterNextRender 执行渲染后逻辑
- 04管理异步数据与手动检测
- 05在 zoneless 模式下测试
适用场景
- 01将 Angular 应用迁移到 zoneless 模式
- 02在渲染后执行 DOM 初始化
- 03为无 Zone 应用编写测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ oguzhan18/ angular-ecosystem-skills --skill angular-zoneless安装后在 Claude Code 中输入/angular-zoneless确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/discussions/_INDEX.mdreferences/docs/_INDEX.mdreferences/issues/_INDEX.mdreferences/releases/_INDEX.md详细介绍
Angular 无 Zone
版本: Angular 19+(2025) 标签: 无 Zone、变更检测、Signals、响应式
API 变更
本节介绍近期特定版本的 API 变更。
-
新增:provideZonelessChangeDetection — 启用无 Zone 模式 来源
-
新增:afterNextRender — 无需 zone.js,在渲染后运行代码
-
新增:实验性无 Zone — Angular 17 起可用,Angular 19+ 中稳定
-
新增:signal() + computed() — 无需 zone.js 即可运行
最佳实践
- 启用无 Zone 变更检测
export const appConfig: ApplicationConfig = {
providers: [
provideZonelessChangeDetection()
]
};
- 使用 signals 实现响应式
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<p>Count: {{ count() }}</p>
<p>Double: {{ double() }}</p>
`
})
export class CounterComponent {
count = signal(0);
double = computed(() => this.count() * 2);
increment() {
this.count.update(c => c + 1);
}
}
- 使用 afterNextRender 执行 DOM 操作
constructor() {
afterNextRender(() => {
// Runs after rendering, outside zone
this.initChart();
});
}
- 使用 afterRender 执行重复操作
constructor() {
afterRender(() => {
// Runs after every render
});
}
- 在没有 zone.js 的情况下处理异步操作
@Component({
template: `
@if (data$ | async; as data) {
{{ data.name }}
}
`
})
export class AsyncComponent {
data$ = from(fetch('/api/data')).pipe(
share()
);
}
- 按需手动使用 ChangeDetectorRef
constructor(private cdr: ChangeDetectorRef) {}
update() {
this.value = newValue;
this.cdr.markForCheck();
}
- 从 polyfills 中移除 zone.js
// polyfills.ts
// Remove or comment out zone.js import
// import 'zone.js';
- 使用 untracked 进行非响应式读取
import { untracked } from '@angular/core';
ngOnInit() {
// Read without creating dependency
const value = untracked(() => this.signal());
}
- 处理浏览器事件
@HostListener('click')
onClick() {
// Works without zone.js
this.count.update(c => c + 1);
}
- 在无 Zone 模式下测试
TestBed.configureTestingModule({
providers: [
provideZonelessChangeDetection()
]
});
评论
支持 Markdown