angular-cdk

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

@angular/cdk (Component Dev Kit)

@angular/cdk (Component Dev Kit)

Version: 21.0.3 (Feb 2026) Tags: Accessibility, Drag & Drop, Overlay, Virtual Scroll, Portal
References: Docs — official CDK documentation • GitHubAPI
版本: 21.0.3(2026年2月) 标签: 可访问性、拖拽、浮层、虚拟滚动、Portal
参考资料: 文档 — CDK官方文档 • GitHubAPI

API Changes

API变更

This section documents recent version-specific API changes.
  • NEW: CDK overlays now use browser's built-in popovers for improved accessibility source
  • NEW: Angular 19 signal-based APIs — Modern signal integration for CDK components
  • NEW: Improved focus management — Better
    cdkTrapFocus
    and
    cdkFocusRegion
    support
  • NEW: Drag & Drop improvements — Enhanced item copying between lists
  • DEPRECATED: Legacy overlay strategies — Prefer scroll strategy configuration over deprecated approaches
本节记录了最近版本的特定API变更内容。
  • 新增:CDK overlays现在使用浏览器内置的弹出层以提升可访问性 来源
  • 新增:Angular 19 基于signal的API — CDK组件已接入现代化signal集成
  • 新增:优化的焦点管理 — 更好的
    cdkTrapFocus
    cdkFocusRegion
    支持
  • 新增:拖拽功能优化 — 增强了列表间的条目复制能力
  • 已弃用:旧版overlay策略 — 推荐使用滚动策略配置,而非已弃用的实现方式

Best Practices

最佳实践

  • Use CDK for custom UI components — Build your own components without Material styling
ts
import { OverlayModule } from '@angular/cdk/overlay';
import { PortalModule } from '@angular/cdk/portal';

@Component({
  standalone: true,
  imports: [OverlayModule, PortalModule],
  // ...
})
export class CustomDropdownComponent {}
  • Use Overlay for floating panels — Tooltips, dropdowns, modals
ts
import { OverlayRef, Overlay } from '@angular/cdk/overlay';

export class TooltipService {
  private overlayRef: OverlayRef;

  constructor(private overlay: Overlay) {
    this.overlayRef = this.overlay.create({
      hasBackdrop: true,
      positionStrategy: this.overlay.position()
        .connectedTo(origin, { originX: 'center', originY: 'bottom' })
        .withOffsetX(0)
        .withOffsetY(8)
    });
  }
}
  • Use Drag & Drop for sortable lists
ts
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';

drop(event: CdkDragDrop<string[]>) {
  if (event.previousContainer === event.container) {
    moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
  } else {
    transferArrayItem(
      event.previousContainer.data,
      event.container.data,
      event.previousIndex,
      event.currentIndex
    );
  }
}
  • Use Virtual Scroll for large lists
ts
import { ScrollingModule } from '@angular/cdk/scrolling';

@Component({
  standalone: true,
  imports: [ScrollingModule],
  template: `
    <cdk-virtual-scroll-viewport itemSize="50" class="viewport">
      <div *cdkVirtualFor="let item of items">{{item.name}}</div>
    </cdk-virtual-scroll-viewport>
  `
})
export class ListComponent {}
  • Use Portal for dynamic content
ts
import { DomPortalOutlet, TemplatePortal } from '@angular/cdk/portal';

@Component({ template: `<ng-template #dialogTemplate>Content</ng-template>` })
export class DialogComponent {
  @ViewChild('dialogTemplate') dialogTemplate!: TemplatePortal;

  attach() {
    const portalOutlet = new DomPortalOutlet(this.document.body);
    portalOutlet.attach(this.dialogTemplate);
  }
}
  • Use A11y utilities for accessibility
ts
import { A11yModule, CdkTrapFocus, LiveAnnouncer } from '@angular/cdk/a11y';

@Component({
  standalone: true,
  imports: [A11yModule],
  template: `
    <div cdkTrapFocus>
      <button cdkFocusInitial>First</button>
      <button>Second</button>
    </div>
  `
})
export class AccessibleComponent {
  constructor(private liveAnnouncer: LiveAnnouncer) {
    this.liveAnnouncer.announce('Message for screen readers');
  }
}
  • Use Layout for responsive breakpoints
ts
import { LayoutModule } from '@angular/cdk/layout';

@Component({
  standalone: true,
  imports: [LayoutModule],
  template: `
    <div *ngIf="isHandset$ | async">
      Mobile content
    </div>
  `
})
export class ResponsiveComponent {
  isHandset$ = this.breakpointObserver.observe('(max-width: 599px)');
}
  • 自定义UI组件请使用CDK — 你可以在不引入Material样式的前提下构建自己的组件
ts
import { OverlayModule } from '@angular/cdk/overlay';
import { PortalModule } from '@angular/cdk/portal';

@Component({
  standalone: true,
  imports: [OverlayModule, PortalModule],
  // ...
})
export class CustomDropdownComponent {}
  • 悬浮面板请使用Overlay — 比如工具提示、下拉框、模态框
ts
import { OverlayRef, Overlay } from '@angular/cdk/overlay';

export class TooltipService {
  private overlayRef: OverlayRef;

  constructor(private overlay: Overlay) {
    this.overlayRef = this.overlay.create({
      hasBackdrop: true,
      positionStrategy: this.overlay.position()
        .connectedTo(origin, { originX: 'center', originY: 'bottom' })
        .withOffsetX(0)
        .withOffsetY(8)
    });
  }
}
  • 可排序列表请使用Drag & Drop
ts
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';

drop(event: CdkDragDrop<string[]>) {
  if (event.previousContainer === event.container) {
    moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
  } else {
    transferArrayItem(
      event.previousContainer.data,
      event.container.data,
      event.previousIndex,
      event.currentIndex
    );
  }
}
  • 长列表请使用Virtual Scroll
ts
import { ScrollingModule } from '@angular/cdk/scrolling';

@Component({
  standalone: true,
  imports: [ScrollingModule],
  template: `
    <cdk-virtual-scroll-viewport itemSize="50" class="viewport">
      <div *cdkVirtualFor="let item of items">{{item.name}}</div>
    </cdk-virtual-scroll-viewport>
  `
})
export class ListComponent {}
  • 动态内容请使用Portal
ts
import { DomPortalOutlet, TemplatePortal } from '@angular/cdk/portal';

@Component({ template: `<ng-template #dialogTemplate>Content</ng-template>` })
export class DialogComponent {
  @ViewChild('dialogTemplate') dialogTemplate!: TemplatePortal;

  attach() {
    const portalOutlet = new DomPortalOutlet(this.document.body);
    portalOutlet.attach(this.dialogTemplate);
  }
}
  • 可访问性功能请使用A11y工具集
ts
import { A11yModule, CdkTrapFocus, LiveAnnouncer } from '@angular/cdk/a11y';

@Component({
  standalone: true,
  imports: [A11yModule],
  template: `
    <div cdkTrapFocus>
      <button cdkFocusInitial>First</button>
      <button>Second</button>
    </div>
  `
})
export class AccessibleComponent {
  constructor(private liveAnnouncer: LiveAnnouncer) {
    this.liveAnnouncer.announce('Message for screen readers');
  }
}
  • 响应式断点请使用Layout模块
ts
import { LayoutModule } from '@angular/cdk/layout';

@Component({
  standalone: true,
  imports: [LayoutModule],
  template: `
    <div *ngIf="isHandset$ | async">
      Mobile content
    </div>
  `
})
export class ResponsiveComponent {
  isHandset$ = this.breakpointObserver.observe('(max-width: 599px)');
}