面试题答案
一键面试模块划分策略
- 功能模块划分
- 按照业务功能划分模块,如用户管理模块、订单管理模块、报表模块等。每个模块负责独立的业务功能,这样使得代码结构清晰,易于维护和扩展。例如,用户管理模块可以包含用户的增删改查功能相关的组件、服务和路由。
- 在 Angular 中,使用
ng generate module
命令创建模块。在模块的@NgModule
装饰器中,通过imports
引入其他依赖模块,declarations
声明模块内的组件、指令和管道,exports
导出需要在其他模块中使用的组件等。
- 共享模块
- 创建共享模块,用于存放可复用的组件、指令和管道。例如,通用的按钮组件、加载指示器组件等。共享模块可以被多个功能模块导入使用,减少代码冗余。
- 在共享模块中,将可复用的内容声明并导出。同时,对于共享模块依赖的其他模块,如
CommonModule
等,也要正确引入。
组件复用机制
- 通用组件库
- 建立一个通用组件库,将一些基础的、可复用性高的组件放入其中。如按钮、输入框、表格等组件。这些组件应该设计得具有高度的灵活性,通过输入属性(
@Input()
)来定制外观和行为。 - 例如,一个通用的按钮组件可以通过
@Input()
接收按钮的文本、颜色、大小等属性,使得在不同的业务场景下都能复用该按钮组件。
- 建立一个通用组件库,将一些基础的、可复用性高的组件放入其中。如按钮、输入框、表格等组件。这些组件应该设计得具有高度的灵活性,通过输入属性(
- 组件继承与组合
- 继承:对于一些具有相似功能和结构的组件,可以通过继承来复用代码。例如,有一个基础的表格组件,不同业务模块中的表格可能在基础表格的功能上有一些扩展,这时可以创建子类继承基础表格组件,并在子类中扩展功能。
- 组合:使用 Angular 的
ng-content
指令实现组件组合。比如,创建一个卡片组件,卡片内部的内容可以由外部传入,这样可以在不同场景下复用卡片组件并填充不同的内容。
路由配置优化
- 路由懒加载
- 对于大型应用,使用路由懒加载可以提高应用的初始加载性能。通过在路由配置中设置
loadChildren
属性来实现懒加载。例如:
- 对于大型应用,使用路由懒加载可以提高应用的初始加载性能。通过在路由配置中设置
const routes: Routes = [
{
path: 'user',
loadChildren: () => import('./user/user.module').then(m => m.UserModule)
}
];
- 这样,只有当用户访问到 `user` 路由时,才会加载 `UserModule` 模块及其相关的代码,减少初始加载的代码量。
2. 路由守卫
- 使用路由守卫来保护路由,确保只有满足特定条件的用户才能访问某些路由。例如,使用 CanActivate
守卫来验证用户是否已经登录:
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(): boolean {
if (this.authService.isLoggedIn()) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}
- 在路由配置中使用该守卫:
const routes: Routes = [
{
path: 'admin',
canActivate: [AuthGuard],
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
}
];
结合 NgRx 提升可维护性和性能
- 状态管理架构
- Store:整个应用的状态存储在一个单一的
Store
中。通过@ngrx/store
库的StoreModule.forRoot
方法来初始化根状态。例如:
- Store:整个应用的状态存储在一个单一的
import { NgModule } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import { appReducer } from './app.reducer';
@NgModule({
imports: [
StoreModule.forRoot({ app: appReducer })
]
})
export class AppStoreModule {}
- **Actions**:定义各种动作(`Actions`)来描述对状态的修改意图。例如,定义一个 `LOGIN_SUCCESS` 动作:
import { createAction } from '@ngrx/store';
export const loginSuccess = createAction(
'[Auth] Login Success',
(user: User) => ({ user })
);
- **Reducers**:根据接收到的 `Actions` 来更新状态。例如,在 `app.reducer.ts` 中:
import { createReducer, on } from '@ngrx/store';
import { loginSuccess } from './auth.actions';
export interface AppState {
user: User | null;
}
const initialState: AppState = {
user: null
};
export const appReducer = createReducer(
initialState,
on(loginSuccess, (state, { user }) => ({...state, user }))
);
- 性能优化
- Memoization:NgRx 使用
Memoization
技术来避免不必要的状态更新。当状态没有发生实际变化时,不会触发组件的重新渲染,从而提高性能。 - Selector:使用
Selector
来从Store
中获取状态。Selector
也具有Memoization
功能,只有当所依赖的状态发生变化时才会重新计算。例如:
- Memoization:NgRx 使用
import { createSelector } from '@ngrx/store';
import { AppState } from './app.state';
export const selectUser = createSelector(
(state: AppState) => state.user,
(user) => user
);
- 在组件中通过 `selectUser` 获取用户状态,这样可以确保只有当用户状态变化时组件才会更新。