首页
/ 深入解析 Angular 的 `@angular/common` 公共 API:从 golden API 报告看通用指令、管道与工具库的全貌

深入解析 Angular 的 `@angular/common` 公共 API:从 golden API 报告看通用指令、管道与工具库的全貌

2026-09-07 09:28:40作者:昌雅子Ethen

导读

@angular/common 是 Angular 框架中"最常用"的基础包——我们在模板里写的 *ngIf*ngFor,格式化日期的 date 管道,页面路由所需的 LocationLocationStrategy,乃至现代化图片优化指令 NgOptimizedImage,全部定义于此。本篇文章以当前仓库中的权威 API 契约文档 goldens/public-api/common/index.api.md 为骨架,逐类解读这份由 API Extractor 自动生成的 @angular/common 公共 API 报告:如何读懂 @public / @deprecated / (undocumented) 标记,四大功能族(结构型指令、内置管道、i18n 格式化工具、Location 导航底层)各暴露了哪些符号与签名,哪些接口是过时/已弃用需要迁移的,以及如何通过 pnpm public-api:check / pnpm public-api:update 验证并更新这份契约。读完你会具备一份可随时对照源码使用的 @angular/common API 速查手册。

这份文档是什么:@angular/common 的 golden API 报告

goldens/public-api/common/index.api.md 的正文第一行即声明其性质:

API Report File for "@angular/common" —— Do not edit this file. It is a report generated by API Extractor.

它是一份机器生成、严禁手改的公共 API 契约文件(golden file),其作用相当于 @angular/common 对外发布面的"快照与金丝雀":

  • 生成来源:由 Microsoft 的 API Extractor 工具对编译产物扫描生成。文件内的 TS 代码块逐条记录了每个被标记为 @publicApi 的导出符号的类型签名。
  • 变更守门员:目录说明见 goldens/README.md —— 仓库"在每次 PR 与提交时作为 Bazel 测试的一部分"运行校验。任何人若无意改变了公共 API(新增、删除、改名、改签名),测试都会失败,从而保证发布到 npm 的包面是可控的。
  • 验证与刷新命令:按 goldens/README.md 的说明,本地校验或(在有意变更 API 后)刷新 golden 使用:
pnpm public-api:check    # 校验当前源码导出与 golden 一致
pnpm public-api:update   # 用当前导出结果覆盖刷新 golden

从源码侧看,这份报告的导出面由 packages/common/src/common.ts 这个"总出口"统一编排,再经 packages/common/index.tspackages/common/public_api.ts 暴露;而 npm 元信息(包描述 "Angular - commonly needed directives and services"、peerDependencies 要求 @angular/corerxjs ^6.5.3 || ^7.4.0、Node 引擎版本等)位于 packages/common/package.json

读这份报告前必须知道的 4 类标记

  1. // @public:稳定公共 API,可放心使用,也是 golden 保护的对象。
  2. // @public @deprecated:仍被导出以向后兼容,但官方已建议迁移。本文件中 NgIfNgForOfNgSwitchDatePipe 的时间戳旧令牌、全部 getLocale* 系列查询函数等都带有该标记。
  3. (undocumented):该符号没有 JSDoc 文档注释,仅代表"文档缺失",不代表内部实现——它们同样属于公共面。
  4. 静态字段 ɵfac / ɵprov / ɵdir / ɵpipe / ɵmod / ɵinj:Angular AOT 编译器为组件/指令/管道/模块生成的编译期元数据声明。例如 DatePipeɵpipe 显示为 i0.ɵɵPipeDeclaration<DatePipe, "date", true>,说明它注册为模板名 dateɵfac 中的 {optional: true} 表示构造参数可空注入(如 DatePipe 的默认时区参数)。日常开发无需直接使用它们,但读 API 报告时它们能佐证"该符号确实是指令/管道/服务"。

另外注意报告中的别名导出技巧:当类型名与内部实现名冲突时,报告会以 Location_2NgForOfPopStateEvent_2 形式显示再 export { ... as Location } 等;同时 DOCUMENTIMAGE_CONFIGImageConfig 三个符号直接以 export { DOCUMENT } 的方式@angular/core 再导出(见报告 import 区与文件尾部),这说明它们的主人是 core 包,@angular/common 只是向前兼容地转发。

CommonModule:所有指令与管道的聚合入口

报告里的 CommonModule 类本身几乎无方法,关键信息集中在它的 ɵinj / ɵmod 声明中。对照 packages/common/src/common_module.ts 的实现可以确认:它是一个空壳 @NgModule,只做一件事——imports: [COMMON_DIRECTIVES, COMMON_PIPES] 并原样 exports

也就是说,只要在模块(或在 standalone 组件中 imports)引入 CommonModule,就可以一次性获得全部内置指令与管道。从报告里 ɵmod 的声明可以数出它导出的完整名单:

  • 指令(10 个)NgClassNgComponentOutletNgForOfNgIfNgTemplateOutletNgStyleNgSwitchNgSwitchCaseNgSwitchDefaultNgPluralNgPluralCase
  • 管道(14 个)AsyncPipeUpperCasePipeLowerCasePipeJsonPipeSlicePipeDecimalPipePercentPipeTitleCasePipeCurrencyPipeDatePipeI18nPluralPipeI18nSelectPipeKeyValuePipe

报告特意注明该模块不包含 Location 相关 Provider("does not contain the location providers"),因为这些服务需要平台相关的实现(浏览器历史 API vs. 服务器环境),通常由 @angular/platform-browserBrowserModule 负责装配——这也是"新建 CLI 项目时 BrowserModule 会被自动包含"的原因。

结构型指令家族:条件渲染、循环、样式绑定与动态组件

该组指令的源码位于 packages/common/src/directives。报告给出了每个指令的输入(ɵdiralias 即模板属性名)与 required 标记,可用于精确的模板写法参考。

NgClassNgStyle:动态 class / style 绑定

两者都实现 DoCheck,构造参数为 ElementRef + Renderer2NgStyle 还额外注入 KeyValueDiffers 做变更检测优化)。NgClassɵdir 选择器是 [ngClass],它把宿主元素的 class 属性也接收为输入 klass(alias class)。模板可用以下任一形态喂给 ngClass

  • 字符串:ngClass="foo bar"
  • 数组:ngClass="['foo', 'bar']"
  • Set<string>
  • 键值对象:{ 'foo': isFoo }

NgIf / NgForOf / NgSwitch*:已被内置控制流取代(@deprecated)

这是本报告中最重要的迁移信号NgIfNgForOfNgSwitchNgSwitchCaseNgSwitchDefault 全部被标记为 @deprecated。但它们的类与辅助类型仍保留并被 CommonModule 导出,以兼容存量代码:

  • NgIf:模板守卫 ngTemplateGuard_ngIf: 'binding' 允许窄化类型(ngIffalse | 0 | '' | null | undefined 时上下文被 Exclude),配合 ngIfThen / ngIfElse 模板引用与上下文类 NgIfContext(含 $implicitngIf 属性)。
  • NgForOf(导出别名为 NgFor):类型签名 NgForOf<T, U extends NgIterable<T>>,支持 ngForOfngForTrackBy: TrackByFunction<T>(性能优化必配)、ngForTemplate;上下文类 NgForOfContext 提供 $implicitindexcount 及派生属性 first / last / even / odd
  • NgSwitch 体系由三件套组成:宿主 [ngSwitch]、匹配分支 [ngSwitchCase]、兜底 [ngSwitchDefault]

若你正在编写新代码,应优先采用 Angular 内置的 @if / @for / @switch 块语法;*ngIf*ngFor[ngSwitch] 仅用于维护遗留代码。

NgPlural / NgPluralCase:复数规则分支

两者都依赖 NgLocalization(基类,只声明抽象方法 getPluralCategory(value, locale?))。默认实现 NgLocaleLocalization 依据 CLDR 复数分类(zero / one / two / few / many / other,见 Plural 枚举)决定显示哪条分支,用于"1 item / 2 items"这类国际化文案;ɵfac 显示 NgPluralCase 的值来自宿主元素属性 ngPluralCase

NgTemplateOutletNgComponentOutlet:模板与组件的动态插入

  • NgTemplateOutlet<C>(源码 ng_template_outlet.ts)接收三个输入:ngTemplateOutlet: TemplateRef<C>ngTemplateOutletContext$implicit 语义的上下文数据)、ngTemplateOutletInjector(可传 'outlet' 字面量以继承宿主注入器)。
  • NgComponentOutlet<T> 在 v17+ 之后的签名体现了现代 standalone 生态:除核心 ngComponentOutlet: Type<T> 外,还支持 ngComponentOutletInputs?: Record<string, unknown>(直接以键值对象注入组件输入,等价 @Input 绑定)、ngComponentOutletInjectorngComponentOutletEnvironmentInjectorngComponentOutletContent(投影内容节点)、ngComponentOutletNgModule,并提供只读 getter componentInstance 访问动态创建出的组件实例。

内置管道(Pipes):模板数据变换工具箱

管道实现集中于 packages/common/src/pipes,全部为 standalone 管道ɵpipe 声明第三参为 true),可脱离模块直接 imports 使用。每个管道的 transform 都按 TypeScript 重载分列了"常规输入"与"null / undefined 输入",后者一律返回 null——这是 Angular 管道对空值友好的统一约定。

管道(模板名) 核心签名 说明
AsyncPipeasync `transform(obj: Observable Subscribable
UpperCasePipe / LowerCasePipe (value: string): string 大小写转换
TitleCasePipe (value: string): string 每个词首字母大写
JsonPipe (value: unknown): string JSON.stringify 的模板封装,调试利器
SlicePipe 数组 / 字符串切片 (value, start, end?) 语义类似 Array.prototype.slice / String.prototype.slice,支持负索引
DecimalPipenumber (value: number | string, digitsInfo?, locale?): string 数字分组与精度,digitsInfo 形如 "1.2-2"(minIntegerDigits.minFractionDigits-maxFractionDigits)
PercentPipepercent (value: number | string, digitsInfo?, locale?): string 数字乘以 100 后带 %
CurrencyPipecurrency (value, currencyCode?, display?, digitsInfo?, locale?): string display 可为 'code' | 'symbol' | 'symbol-narrow' | string | boolean,决定输出货币代码还是符号;构造函数可选 _defaultCurrencyCode
DatePipedate (value: Date | string | number, format?, timezone?, locale?): string 见下
KeyValuePipekeyvalue (input: ReadonlyMap | Record, compareFn?): Array<KeyValue> 把 Map / 对象摊平成 {key, value} 数组以便 @for 遍历,支持自定义 compareFn 排序
I18nSelectPipei18nSelect (value: string, mapping: {[k]: string}): string 按键值从映射表挑文案
I18nPluralPipei18nPlural (value: number, pluralMap: {[count]: string}, locale?): string 复数文案;底层依赖 NgLocalization.getPluralCategory 决定匹配 =0=1other 等键

关于 DatePipe 的两组配置令牌

DatePipe 是本包的"重武器",除默认 'mediumDate' 等预置格式外还接受 CLDR 日期格式串。报告中与它相关的令牌值得关注:

  • DATE_PIPE_DEFAULT_OPTIONS: InjectionToken<DatePipeConfig>全局默认配置,其中 DatePipeConfig 接口只有两个可选字段 dateFormat?: stringtimezone?: string。提供该令牌即可为整个应用的 date 管道设定统一格式与默认时区(provider 位于应用入口的 providers)。
  • DATE_PIPE_DEFAULT_TIMEZONE: InjectionToken<string>:旧版单一时区令牌,已在报告中标记 @deprecated,新代码应改用 DATE_PIPE_DEFAULT_OPTIONS

DatePipeɵfac 显示三个构造参数(locale、可选默认时区、可选默认配置),其中后两者标注 {optional: true},即令牌缺失时自动降级为 CLDR 默认值。

i18n 数字/日期格式化:函数式工具与(已弃用的)Locale 查询 API

不依赖 DI、可在任意 TS 代码中直接调用的纯函数来自 packages/common/src/i18n 下的 format_date.tsformat_number.tslocale_data_api.ts,在 packages/common/src/common.ts 中统一导出。

四个核心格式化函数

函数 签名 等价管道
formatDate (value: string | number | Date, format: string, locale: string, timezone?: string): string date
formatNumber (value: number, locale: string, digitsInfo?: string): string number
formatPercent (value: number, locale: string, digitsInfo?: string): string percent
formatCurrency (value: number, locale: string, currency: string, currencyCode?: string, digitsInfo?: string): string currency

它们与对应管道共用同一套内部实现(管道只是模板层封装),适合在 Service / Effect / 日志等非模板场景做本地化格式化。

registerLocaleData 与"即将整体退役"的 getLocale*

  • registerLocaleData(data, localeId?, extraData?):运行时把从 @angular/common/locales 子路径导入的 locale 数据注册进 DatePipe / number 管道等使用的本地化数据仓库,以实现非全局导入的按需加载。
  • 报告用极长的篇幅列出约 25 个 getLocale* 函数(getLocaleIdgetLocaleMonthNamesgetLocaleDateFormatgetLocaleFirstDayOfWeekgetLocaleCurrencySymbolgetLocalePluralCasegetNumberOfCurrencyDigits……),它们全部标注 @deprecated,连同 getCurrencySymbol 一起,属于历史遗留的 locale 数据查询 API。新代码如需读取 CLDR 派生数据,应改用 @angular/common/locales 直接提供的数据结构。
  • 支撑这些函数的一批过时枚举/常量也随报告被列出并标记废弃:FormatWidthShort=0, Medium=1, Long=2, Full=3)、FormStyleFormat / Standalone)、TranslationWidthNarrow=0, Abbreviated=1, Wide=2, Short=3)、NumberFormatStyleDecimal/Percent/Currency/Scientific)、NumberSymbol(含 DecimalGroupMinusSignPerMilleCurrencyDecimal 等 14 个成员)、PluralZero/One/Two/Few/Many/Other)、WeekDaySunday=0Saturday=6)、Time{hours, minutes})。使用它们的既有代码应规划迁移,但它们仍被导出,不会立刻中断。
  • 未废弃的辅助类型只有少量,例如 getCurrencySymbol(code, 'wide'|'narrow', locale?) 之外的 NgLocalization / NgLocaleLocalization 抽象与默认实现(用于复数管道,前文已述)。

Location 导航家族:URL 读写与路由策略的底层抽象

报告的第二大板块是"导航与地址栏管理",源码见 packages/common/src/location,是整个 @angular/router 依赖浏览器/服务器 URL 行为的桥梁。其层级设计如下:

LocationStrategy(抽象:back/forward/path/prepareExternalUrl/pushState/replaceState/onPopState/getBaseHref/getState/historyGo?)
├── PathLocationStrategy            ← 默认策略,HTML5 History API(pushState/replaceState)
│     └── NoTrailingSlashPathLocationStrategy     ← 输出 URL 不含尾斜杠
│     └── TrailingSlashPathLocationStrategy       ← 输出 URL 强制带尾斜杠
└── HashLocationStrategy            ← hash 模式(#/path),适合静态托管
PlatformLocation(抽象:href/hash/pathname/search/hostname/port/protocol 访问器 + onPopState/onHashChange/pushState…)
└── BrowserPlatformLocation         ← 浏览器 DOM 实现,含 getBaseHrefFromDOM()

值得逐条记录的关键导出:

  • Location(报告中以 Location_2 内部名导出):高层服务,注入 LocationStrategy,提供 go(path, query?, state?)replaceStateback/forward/historyGoisCurrentPathEqualTopath(includeHash?)subscribe(onNext)(监听 PopStateEvent)以及静态工具 joinWithSlashnormalizeQueryParamsstripTrailingSlashnormalize
  • LocationStrategyPlatformLocation:抽象基类,真正的平台差异(DOM History API vs. 服务端占位)都被隔离在 PlatformLocation 的实现中;PlatformLocation 同时暴露可取消订阅的 onPopState / onHashChange(返回 VoidFunction)。
  • PathLocationStrategy 构造器 (platformLocation, href?) 中的 href 为可选,用于覆盖 <base href> 探测结果;HashLocationStrategy 构造器 (platformLocation, baseHref?) 同理由 ɵfac 标为 {optional: true}
  • 两个新的 URL 规范化策略:NoTrailingSlashPathLocationStrategyTrailingSlashPathLocationStrategy 仅覆写 prepareExternalUrl,用于强制/去除 URL 尾斜杠——适合 SEO 规范或反向代理路由规则严格的部署场景。
  • 令牌:APP_BASE_HREF: InjectionToken<string>(手动指定 <base>,供 Location 计算内部 URL);LOCATION_INITIALIZED: InjectionToken<Promise<any>>(在应用初始化前等待 location 就绪)。
  • 事件类型:PopStateEvent(内部名 PopStateEvent_2,可选字段 pop? / state? / type? / url?)、LocationChangeEventtype + state)、监听器类型 LocationChangeListener

浏览器侧的现代导航抽象 PlatformNavigation

报告中还出现一个面向未来 Web 标准的抽象类 PlatformNavigation(源码位于 packages/common/src/navigation),它把浏览器 Navigation APInavigatereloadtraverseToentriescanGoBack/canGoForwardcurrentEntrytransition,以及 oncurrententrychange / onnavigate / onnavigatesuccess / onnavigateerror 等事件处理器)收拢成一个可注入抽象,供浏览器之外的平台(如 SSR)提供兼容实现。它复用了 @angular/core 中一批以 ɵ 前缀的内部类型(ɵNavigationɵNavigationResult 等),属于"框架内部走在前沿、未来可能公开"的接口。

NgOptimizedImage:基于 img[ngSrc] 指令的图片加载优化体系

从报告可见,图片优化并非孤立的一个指令,而是一整套公开面(源码目录 packages/common/src/directives/ng_optimized_image):

  • 指令 NgOptimizedImage,选择器 img[ngSrc]。各输入及其模板 alias:
    • ngSrc(required):源码地址;
    • ngSrcset / sizes:响应式 srcset 与 sizes(ngSrcset 可自动基于宽度指令生成);
    • width / height必须提供以预留布局空间、防 CLS;
    • priority:标记 LCP 首屏图(等价 fetchpriority=high 且禁用懒加载);
    • loading: 'lazy' | 'eager' | 'auto'decoding: 'sync' | 'async' | 'auto'
    • fill:填充父容器模式的响应式图;
    • placeholder: boolean | stringplaceholderConfig?: ImagePlaceholderConfig{blur?: boolean},指示是否生成模糊占位)——指令内部通过 generatePlaceholder / shouldBlurPlaceholder 两个受保护方法实现;
    • loaderParams?: {[k: string]: any}:透传给 loader 的自定义参数;
    • disableOptimizedSrcset:关闭自动 srcset 生成。
  • Loader 机制IMAGE_LOADER: InjectionToken<ImageLoader> 定义 loader 函数类型 ImageLoader = (config: ImageLoaderConfig) => stringImageLoaderConfig 包含 srcwidth?height?isPlaceholder?loaderParams?。用户可注入自定义 loader 把 ngSrc 拼接成 CDN 地址。
  • 内置 CDN Loader ProviderprovideCloudinaryLoader(path)provideCloudflareLoader(path)provideImgixLoader(path)provideImageKitLoader(path)provideNetlifyLoader(path?)(最后一个参数可省略)。provider 只需在应用 providers 中调用一次。
  • 辅助令牌PRECONNECT_CHECK_BLOCKLIST: InjectionToken<(string | string[])[]> 用于屏蔽对某些域名的自动 preconnect 检查告警;IMAGE_CONFIG 与其类型 ImageConfig@angular/core 再导出(该令牌承载全局图片默认配置,如默认断点)。

平台判定、依赖注入令牌与基础设施

剩余导出多属于"跨平台开发基础设施",源码对应 packages/common/src 根目录下的若干小文件:

  • isPlatformBrowser(platformId) / isPlatformServer(platformId):平台判定函数,通常配合 @angular/corePLATFORM_ID 令牌注入使用(内部字符串常量 PLATFORM_BROWSER_ID / PLATFORM_SERVER_ID 仅以 ɵ 前缀私有导出,未进公共面)。
  • DOCUMENT:从 @angular/core 再导出的 document 注入令牌(SSR 环境安全访问 DOM 的推荐方式)。
  • VERSION: Version:包版本对象(发布时由 0.0.0-PLACEHOLDER 替换为真实版本号)。
  • XhrFactory:抽象类,唯一方法 build(): XMLHttpRequest,是 HTTP 底层 XHR 工厂的可注入抽象。
  • ViewportScroller:抽象滚动服务,方法有 getScrollPosition / scrollToPosition(position, options?) / scrollToAnchor(anchor, options?) / setOffset / setHistoryScrollRestoration('auto' | 'manual');其 ɵprov 声明表明运行时在多态 Provider(BrowserViewportScroller 或服务端的 NullViewportScroller)间解析,Router 的滚动位置恢复功能正是基于它。
  • 注入令牌与事件:APP_BASE_HREFLOCATION_INITIALIZED(见 Location 一节)、LocationChangeEvent / LocationChangeListener

一份务实的开发对照清单

把报告读薄,可以沉淀出几条可直接指导日常开发的结论:

  1. 新模板优先内置控制流*ngIf*ngFor[ngSwitch] 三个指令族在报告中被整体标记 @deprecated,新代码应使用 @if / @for / @switch*ngIf 配套的 then / else@if / @else 更直观。
  2. 数字与日期管道的扩展能力在令牌与纯函数上DATE_PIPE_DEFAULT_OPTIONSdateFormat + timezone)可统一全局日期默认值;模板之外用 formatDate / formatCurrency / formatNumber / formatPercent;新增语言用 registerLocaleData + @angular/common/locales
  3. 不要在新代码里写 getLocale*:整族函数与 FormatWidth / FormStyle / NumberFormatStyle 等枚举均已 @deprecated,属于纯历史遗留接口。
  4. URL 尾斜杠策略是开箱即用的:无需自实现 LocationStrategy,直接换用 TrailingSlashPathLocationStrategyNoTrailingSlashPathLocationStrategy 即可满足规范要求。
  5. 图片性能优化走 ngSrc 全家桶NgOptimizedImage + 一个 provide*Loader Provider + 每张图显式 width/height(或 fill),是 Angular 官方推荐的图片加载方案,相关令牌 IMAGE_LOADERPRECONNECT_CHECK_BLOCKLIST 均可按需定制。

小结

@angular/common 的这份 API 报告虽由机器生成、读起来像"符号清单",但它恰恰是框架契约最精确的呈现CommonModule 聚合了多少指令与管道、哪些 API 已进入弃用窗口、Location 抽象如何分层、图片优化体系需要注入哪些令牌——全部可以在 goldens/public-api/common/index.api.md 中对照 packages/common/src/common.ts 及其下的 directives / pipes / location / i18n / navigation 源码逐条验明。在阅读与源码实现存疑时,以这份 golden 为准;当你有意变更公共 API 时,记得用 pnpm public-api:update 刷新契约并用 pnpm public-api:check 守护它。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388