Angular样式指南 #

一、命名规范 #

1.1 文件命名 #

类型 格式 示例
组件 feature.component.ts user-list.component.ts
服务 feature.service.ts user.service.ts
模块 feature.module.ts user.module.ts
指令 feature.directive.ts highlight.directive.ts
管道 feature.pipe.ts truncate.pipe.ts
守卫 feature.guard.ts auth.guard.ts
模型 feature.model.ts user.model.ts
接口 feature.interface.ts user.interface.ts

1.2 组件命名 #

typescript
// 推荐
@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html'
})
export class UserListComponent { }

// 不推荐
@Component({
  selector: 'userList',
  templateUrl: './userlist.html'
})
export class userList { }

1.3 服务命名 #

typescript
// 推荐
@Injectable({ providedIn: 'root' })
export class UserService { }

// 不推荐
@Injectable()
export class UserSvc { }

1.4 选择器命名 #

typescript
// 推荐:使用kebab-case
selector: 'app-user-card'
selector: 'app-user-list-item'

// 不推荐
selector: 'appUserCard'
selector: 'UserCard'

二、组件规范 #

2.1 组件结构 #

typescript
@Component({
  selector: 'app-user-card',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './user-card.component.html',
  styleUrl: './user-card.component.css',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserCardComponent implements OnInit, OnDestroy {
  @Input() user: User;
  @Output() selected = new EventEmitter<User>();
  
  private destroy$ = new Subject<void>();
  
  constructor(private userService: UserService) {}
  
  ngOnInit(): void {}
  
  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }
  
  onSelect(): void {
    this.selected.emit(this.user);
  }
}

2.2 成员排序 #

typescript
export class ExampleComponent {
  // 1. 输入属性
  @Input() user: User;
  @Input() isActive = false;
  
  // 2. 输出属性
  @Output() selected = new EventEmitter<User>();
  
  // 3. 公共属性
  isLoading = false;
  users: User[] = [];
  
  // 4. 私有属性
  private subscription: Subscription;
  
  // 5. 构造函数
  constructor(private userService: UserService) {}
  
  // 6. 生命周期钩子
  ngOnInit(): void {}
  ngOnDestroy(): void {}
  
  // 7. 公共方法
  loadUsers(): void {}
  
  // 8. 私有方法
  private handleError(error: Error): void {}
}

2.3 使用OnPush #

typescript
@Component({
  selector: 'app-user-list',
  template: '...',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserListComponent {
  @Input() users: User[];
}

三、服务规范 #

3.1 服务结构 #

typescript
@Injectable({ providedIn: 'root' })
export class UserService {
  private readonly apiUrl = '/api/users';
  private usersSubject = new BehaviorSubject<User[]>([]);
  
  users$ = this.usersSubject.asObservable();
  
  constructor(private http: HttpClient) {}
  
  getUsers(): Observable<User[]> {
    return this.http.get<User[]>(this.apiUrl);
  }
  
  getUser(id: number): Observable<User> {
    return this.http.get<User>(`${this.apiUrl}/${id}`);
  }
  
  createUser(user: User): Observable<User> {
    return this.http.post<User>(this.apiUrl, user);
  }
}

3.2 单一职责 #

typescript
// 推荐:职责单一
@Injectable({ providedIn: 'root' })
export class UserService { }

@Injectable({ providedIn: 'root' })
export class AuthService { }

// 不推荐:职责过多
@Injectable({ providedIn: 'root' })
export class AppService {
  // 用户、认证、产品、订单...
}

四、模板规范 #

4.1 模板结构 #

html
<!-- 推荐 -->
<div class="user-card">
  <h3 class="user-name">{{ user.name }}</h3>
  <p class="user-email">{{ user.email }}</p>
  <button 
    class="btn btn-primary"
    (click)="onSelect()"
    [disabled]="isLoading">
    选择
  </button>
</div>

<!-- 不推荐 -->
<div class="user-card"><h3 class="user-name">{{user.name}}</h3><p class="user-email">{{user.email}}</p><button class="btn btn-primary"(click)="onSelect()"[disabled]="isLoading">选择</button></div>

4.2 属性顺序 #

html
<input
  type="text"
  id="name"
  name="name"
  class="form-control"
  [(ngModel)]="user.name"
  required
  minlength="2"
  #nameInput="ngModel"
/>

4.3 使用新控制流语法 #

html
<!-- Angular 17+ 推荐 -->
@if (users.length > 0) {
  <ul>
    @for (user of users; track user.id) {
      <li>{{ user.name }}</li>
    }
  </ul>
} @else {
  <p>暂无用户</p>
}

<!-- 传统语法 -->
<div *ngIf="users.length > 0; else empty">
  <ul>
    <li *ngFor="let user of users; trackBy: trackById">
      {{ user.name }}
    </li>
  </ul>
</div>
<ng-template #empty>
  <p>暂无用户</p>
</ng-template>

五、样式规范 #

5.1 组件样式 #

typescript
@Component({
  selector: 'app-user-card',
  template: '...',
  styles: [`
    .user-card {
      padding: 16px;
      border-radius: 8px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    }
    
    .user-name {
      font-size: 18px;
      font-weight: bold;
    }
    
    .user-email {
      color: #666;
    }
  `]
})

5.2 使用SCSS #

scss
// variables.scss
$primary-color: #007bff;
$border-radius: 4px;

// user-card.component.scss
@import 'variables';

.user-card {
  padding: 16px;
  border-radius: $border-radius;
  
  .user-name {
    color: $primary-color;
  }
}

六、项目结构 #

6.1 推荐结构 #

text
src/app/
├── core/                      # 核心模块
│   ├── services/
│   │   ├── auth.service.ts
│   │   └── api.service.ts
│   ├── guards/
│   │   └── auth.guard.ts
│   ├── interceptors/
│   │   └── auth.interceptor.ts
│   └── models/
│       └── user.model.ts
├── shared/                    # 共享模块
│   ├── components/
│   │   ├── button/
│   │   └── input/
│   ├── directives/
│   │   └── highlight/
│   └── pipes/
│       └── truncate/
├── features/                  # 功能模块
│   ├── user/
│   │   ├── components/
│   │   ├── services/
│   │   └── user.routes.ts
│   └── product/
│       ├── components/
│       ├── services/
│       └── product.routes.ts
├── app.component.ts
├── app.config.ts
└── app.routes.ts

6.2 功能模块结构 #

text
features/user/
├── components/
│   ├── user-list/
│   │   ├── user-list.component.ts
│   │   ├── user-list.component.html
│   │   └── user-list.component.scss
│   └── user-detail/
│       ├── user-detail.component.ts
│       ├── user-detail.component.html
│       └── user-detail.component.scss
├── services/
│   └── user.service.ts
├── models/
│   └── user.model.ts
└── user.routes.ts

七、编码规范 #

7.1 使用const #

typescript
// 推荐
const MAX_USERS = 100;
const API_URL = '/api/users';

// 不推荐
var maxUsers = 100;
let apiUrl = '/api/users';

7.2 使用接口 #

typescript
// 推荐
interface User {
  id: number;
  name: string;
  email: string;
}

// 不推荐
type User = {
  id: number;
  name: string;
  email: string;
};

7.3 使用可选链 #

typescript
// 推荐
const name = user?.profile?.name;

// 不推荐
const name = user && user.profile && user.profile.name;

7.4 使用空值合并 #

typescript
// 推荐
const name = user?.name ?? 'Unknown';

// 不推荐
const name = user?.name ? user.name : 'Unknown';

八、性能规范 #

8.1 使用trackBy #

typescript
@Component({
  template: `
    <li *ngFor="let user of users; trackBy: trackById">
      {{ user.name }}
    </li>
  `
})
export class UserListComponent {
  trackById(index: number, user: User): number {
    return user.id;
  }
}

8.2 使用OnPush #

typescript
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush
})

8.3 避免内存泄漏 #

typescript
export class ExampleComponent implements OnInit, OnDestroy {
  private destroy$ = new Subject<void>();
  
  ngOnInit() {
    this.service.getData()
      .pipe(takeUntil(this.destroy$))
      .subscribe();
  }
  
  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

九、总结 #

规范 说明
命名规范 使用一致的命名约定
组件规范 单一职责、OnPush
服务规范 providedIn: ‘root’
模板规范 清晰的结构
样式规范 组件封装样式
项目结构 按功能模块组织

下一步:性能优化

最后更新:2026-03-26