angular-zoneless
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAngular Zoneless
Angular Zoneless
Version: Angular 19+ (2025)
Tags: Zoneless, Change Detection, Signals, Reactivity
References: Zoneless Guide • Signals
版本: Angular 19+ (2025)
标签: Zoneless、变更检测、Signals、响应式
参考资料: Zoneless指南 • Signals
API Changes
API变更
This section documents recent version-specific API changes.
-
NEW: provideZonelessChangeDetection — Enable zoneless mode source
-
NEW: afterNextRender — Run code after rendering without zone.js
-
NEW: Experimental Zoneless — Available since Angular 17, stable in Angular 19+
-
NEW: signal() + computed() — Works without zone.js
本部分记录了近期各版本对应的API变动:
-
新增:provideZonelessChangeDetection — 启用无zone模式 来源
-
新增:afterNextRender — 无需zone.js即可在渲染结束后运行代码
-
新增:实验性无zone模式 — 自Angular 17起提供,Angular 19+版本正式稳定
-
新增:signal() + computed() — 无需依赖zone.js即可正常工作
Best Practices
最佳实践
- Enable zoneless change detection
ts
export const appConfig: ApplicationConfig = {
providers: [
provideZonelessChangeDetection()
]
};- Use signals for reactivity
ts
@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);
}
}- Use afterNextRender for DOM operations
ts
constructor() {
afterNextRender(() => {
// Runs after rendering, outside zone
this.initChart();
});
}- Use afterRender for repeated operations
ts
constructor() {
afterRender(() => {
// Runs after every render
});
}- Handle async without zone.js
ts
@Component({
template: `
@if (data$ | async; as data) {
{{ data.name }}
}
`
})
export class AsyncComponent {
data$ = from(fetch('/api/data')).pipe(
share()
);
}- Use ChangeDetectorRef manually when needed
ts
constructor(private cdr: ChangeDetectorRef) {}
update() {
this.value = newValue;
this.cdr.markForCheck();
}- Remove zone.js from polyfills
ts
// polyfills.ts
// Remove or comment out zone.js import
// import 'zone.js';- Use untracked for non-reactive reads
ts
import { untracked } from '@angular/core';
ngOnInit() {
// Read without creating dependency
const value = untracked(() => this.signal());
}- Handle browser events
ts
@HostListener('click')
onClick() {
// Works without zone.js
this.count.update(c => c + 1);
}- Test in zoneless mode
ts
TestBed.configureTestingModule({
providers: [
provideZonelessChangeDetection()
]
});- 启用无zone变更检测
ts
export const appConfig: ApplicationConfig = {
providers: [
provideZonelessChangeDetection()
]
};- 使用Signals实现响应式
ts
@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);
}
}- 对DOM操作使用afterNextRender
ts
constructor() {
afterNextRender(() => {
// Runs after rendering, outside zone
this.initChart();
});
}- 对重复操作使用afterRender
ts
constructor() {
afterRender(() => {
// Runs after every render
});
}- 无需zone.js处理异步逻辑
ts
@Component({
template: `
@if (data$ | async; as data) {
{{ data.name }}
}
`
})
export class AsyncComponent {
data$ = from(fetch('/api/data')).pipe(
share()
);
}- 需要时手动使用ChangeDetectorRef
ts
constructor(private cdr: ChangeDetectorRef) {}
update() {
this.value = newValue;
this.cdr.markForCheck();
}- 从polyfills中移除zone.js
ts
// polyfills.ts
// Remove or comment out zone.js import
// import 'zone.js';- 非响应式读取时使用untracked
ts
import { untracked } from '@angular/core';
ngOnInit() {
// Read without creating dependency
const value = untracked(() => this.signal());
}- 处理浏览器事件
ts
@HostListener('click')
onClick() {
// Works without zone.js
this.count.update(c => c + 1);
}- 在无zone模式下测试
ts
TestBed.configureTestingModule({
providers: [
provideZonelessChangeDetection()
]
});