Angular 18+ 高级教程 – Naming Conversion
前言
命名规范对项目维护是很重要的. Angular 对项目的渗透很大的, 必须做好命名规范, 不然会很乱.
InjectionToken
InjectionToken = UPPER_SNAKE_CARE
const SERVICE_CONFIG = new InjectionToken('ServiceConfig');
variable name 用 UPPER_SNAKE_CARE
InjectionToken 的参数用 PascalCase 或者 UPPER_SNAKE_CARE
Attribute and Property
element attribute and property name = camelCase
angular.io example 有 camelCase 和 kebab-case,不过我看绝大部分都是用 camelCase 居多。
<bank-account bankName="RBC" account-id="4747"></bank-account>
Event
event handler method
如果没有一个具体的执行名字,请不要放 (click)="onClick()" 放 "handleClick()"。
ValidationErrors
ValidationErrors key 用 camelCase
from Angular Docs
不过 built-in 的 minLength 和 maxLength 的 key 是 lowercase 'minlength' 和 'maxlength' 哦,奇葩。
Directive Selector
Angular CDK Derective selector 用 kebab-case 还是 camelCase?
CdkScrollable 指令 kebab-case 和 camelCase 都能接受。
CdkVirtualScrollableElement 指令只能接受 camelCase
CdkHeaderCell 指令只能接受 kebab-case。
显然,它们没有统一规范。不过通常 element 是用 kebab-case,attribute 用 camelCase。遇到例外比如 (th[cdk-header-cell]) 也没办法,只能 follow 它。
组件 attribute selector
通常组件是 tag,指令通常是 attribute。
<my-component myDirective></my-component>
但这也只是通常。
许多情况下组件也可能是 attrbute,这种情况下要用 kebab-case 还是 camelCase 呢?
我觉得像 Angular Material Button 这样使用 kebab-case 挺好的。
当组件的 selector 是 attribute 时使用 kebab-case。
@HostBinding and @HostListener Decorator
官网的 guide 是叫我们尽量用 @HostBinding Decorator 对比在 @Directive host property
但是 Angular Material 一直没有 follow 这个 guide
如今 Angular 正在去 Decorator 化,所以我建议使用 @Directive host property。
Animation CSS Property
依据官网教程,使用 camelCase
我觉得 camelCase 比 kebab-case 好,因为 Web Animation API 是只能使用 camelCase,这样比较统一。
Animation Trigger Name
下面这些是从 Angular Material 源码中抄出来的 Trigger Name:
- detailExpand
- panelAnimation
- state
- transformPanel
- fadeInCalendar
- dialogContainer
- indicatorRotate
- bodyExpansion
- transitionMessages
- transformMenu
- fadeInItems
- transformPanelWrap
- transformPanel
- transform
- indicator
- leftPointer
- rightPointer
- arrowOpacity
- arrowPosition
- allowChildren
- horizontalStepTransition
- verticalStepTransition
- translateTab
没有统一规范,但大部分有 2 个特性
-
对象
比如 panel, Calendar, dialog, body, Messages, Menu, Items 等等
有时候在前面,有时候在后面
-
动作
比如 Expand, transform, fadeIn, Rotate 等等
有时候在前面,有时候在后面,有时候只有对象没有动作。
当然还有一些比较直接的:panelAnimation,state。
我个人的规范是:
-
如果这个 trigger 会被用在多个 element 上,那取个动作名字就好了。
-
如果是用在指定 element 上,最好配个对象名字。
-
如果动作不好取,就直接叫 panelAnimation 或者 panelAnimationState 就好了。
x, y, top, right, bottom, left, vertical, horizontal
vertical 和 horizontal 的抽象叫 orientation (follow Angular Material)
x, y 抽象叫 axis (轴的意思,follow Angular Material)
top, right, bottom, left 抽象叫 position 或 direction (follow Angular Material)
exportAs
参考 Angular Material
指令和组件都可能会有 exportAs,
exportAs 用的是 camelCase,通常名字就和 element tag 或 attribute 一样。
String literal union types
参考 Angular Material 源码
各种 case styles 都有,但绝大多数是 lowercase single word。
通常这些 string literal 会被用在 property 和 class name。
property 是 camelCase,class name 是 kebab-case 所以用这 2 种 case styles 就挺安全的了。
如果遇到冲突,我们可以做一些 conversion。
像这样:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//#region combineToCamelCase export function combineToCamelCase<T1 extends string, T2 extends string>( v1: T1, v2: T2, ): `${Uncapitalize<T1>}${Capitalize<T2>}`; export function combineToCamelCase<T1 extends string, T2 extends string, T3 extends string>( v1: T1, v2: T2, v3: T3, ): `${Uncapitalize<T1>}${Capitalize<T2>}${Capitalize<T3>}`; export function combineToCamelCase<T1 extends string, T2 extends string, T3 extends string, T4 extends string>( v1: T1, v2: T2, v3: T3, v4: T4, ): `${Uncapitalize<T1>}${Capitalize<T2>}${Capitalize<T3>}${Capitalize<T4>}`; export function combineToCamelCase(...values: string[]): string { return values .map((value, index) => index === 0 ? value.substring(0, 1).toLowerCase() + value.substring(1) : value.substring(0, 1).toUpperCase() + value.substring(1), ) .join(''); } //#endregion //#region combineToPascalCase export function combineToPascalCase<T1 extends string, T2 extends string>( v1: T1, v2: T2, ): `${Capitalize<T1>}${Capitalize<T2>}`; export function combineToPascalCase<T1 extends string, T2 extends string, T3 extends string>( v1: T1, v2: T2, v3: T3, ): `${Capitalize<T1>}${Capitalize<T2>}${Capitalize<T3>}`; export function combineToPascalCase<T1 extends string, T2 extends string, T3 extends string, T4 extends string>( v1: T1, v2: T2, v3: T3, v4: T4, ): `${Capitalize<T1>}${Capitalize<T2>}${Capitalize<T3>}${Capitalize<T4>}`; export function combineToPascalCase(...values: string[]): string { return values.map(value => value.substring(0, 1).toUpperCase() + value.substring(1)).join(''); } //#endregion //#region combineToKebabCase export function combineToKebabCase<T1 extends string, T2 extends string>( v1: T1, v2: T2, ): `${Lowercase<T1>}-${Lowercase<T2>}`; export function combineToKebabCase<T1 extends string, T2 extends string, T3 extends string>( v1: T1, v2: T2, v3: T3, ): `${Lowercase<T1>}-${Lowercase<T2>}-${Lowercase<T3>}`; export function combineToKebabCase<T1 extends string, T2 extends string, T3 extends string, T4 extends string>( v1: T1, v2: T2, v3: T3, v4: T4, ): `${Lowercase<T1>}-${Lowercase<T2>}-${Lowercase<T3>}-${Lowercase<T4>}`; export function combineToKebabCase(...values: string[]): string { return values.map(value => value.toLowerCase()).join('-'); } //#endregion
Change or Changes?
Angular Material 在写 @Output 时是用 xxxChange
但 xxxChanges 也有很多地方会使用哦
😂