Angular 17 - QA
Angular Component, Core Directives and Pipes
Angular Component, Core Directives and Pipes
Angular 17 新增了哪些新的方法
?
新增了 @for @empty | @if @else | @switch @case @default
@for @empty 和 *ngFor 的区别
?
更加简单,默认支持 $index, $count, $first, $last, $odd, $even,必须要给 track,可以是方法
@if @else 和 *ngIf 的区别
?
写法更方便
*ngContainer 的作用是什么
?
作为一个占位符,和 React的 <></>类似,通常可以结合其他指令一起使用。不会放到 dom 结构中
ngTemplate 是什么
?
可以定义一个模板元素,可以配合其他语法使用,例如@for @if等。可以用于模板片段,通过ngTemplateOutlet在其他组件中复用
1 | // define |
build-in pipe 有哪些
?date: 'MMM/dd/YYYY', currency: 'CNY', number:'3.3-5', slice:0:2, json, keyvalue
Angular Local Template Querying In Depth
Angular 在组件中如何查找子组件
?
可以使用装饰器 @ViewChild(ComponentClass or \referId),通过class匹配时,多个class也只返回第一个。装饰器可以拿到对应组件下面的所有成员变量。
如果使用 ElementRef加上refId,可以拿到对应的 native dom。也可以使用 @ViewChildren找到多个子项
1 | ('card'|CardComponent) |
什么时候可以操作对应的 dom 或者 component
?
可以在 Angular 提供的 ngAfterViewInit方法中操作,这个方法会在视图加载完成后调用。但是不要在这个方法中修改视图相关的数据,这样会导致渲染的时候出现错误
ngContent 如何使用
?ngContent 可以作为一个占位符,类似于 React 中使用 {this.children()}。作用是将当前组件作为一个高阶组件,接收外部传入的子组件并正确的放置在对应的地方。其中 select 属性可以选择元素或者 class。一个页面可以允许多个 <ngContent/>
Angular Content Projection In Depth
@ViewChild注解和@ContentChild注解的区别
?
当视图中使用了ng-content标签,那么从父组件传入的部分无法被 @ViewChild捕获,因此只能使用@ContentChild来查询该组件。而@ContentChild语法只能用于查询传入的部分视图,无法获取当前 View 中的其他组件。
@ViewChild,@ViewChildren, @ContentChild,@ContentChildren区别
?children表明是查询多个组件
Angular Directives In Depth
Angular Directive 是什么,怎么用?
?
- 增强现有组件功能,可以在该中为现有组件添加或修改属性或者事件
- 可以接受输入元素和方法
@Input和@Output - 可以自定义
Directive实现类似ngIf的操作,通过templateRef和ViewContainer来操作视图的添加和删除 - 将指令通过
exportAs导出后,通过#RefId='direID'的方式可以将它引入文件中,其他地方就可以调用其内部方法 - 通过步骤3导出后,可以通过
@ViewChild查询到该指令1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<course-image [src]="course.iconUrl" *ngxUnless="!course.iconUrl"/>
({
selector: '[ngxUnless]',
standalone: true
})
export class NgxUnlessDirective {
constructor(private templateRef: TemplateRef<any>, private container: ViewContainerRef) {
}
private visible: boolean = false;
()
set ngxUnless(condition: boolean) {
if (!condition && !this.visible) {
this.container.createEmbeddedView(this.templateRef);
this.visible = true;
}
if (condition && this.visible) {
this.container.clear();
this.visible = false;
}
}
}
Angular View Encapsulation In Depth
Angular是怎么保持各个组件之间的 css style 独立的?
?
- 基于组件分为不同的 css 文件,实现不同组件样式文件之间的独立
- 默认使用
Emulated模式,会生成唯一的className来区分 - 支持使用 CSS 模块化
Angular提供了哪些 View Encapsulation?
?
Emulated,默认,Angular会自动生成唯一标志来使CSS互不影响Native,使用浏览器自带的Shadow DOM的API来实现样式隔离,但是浏览器支持有限None,不使用Encapsulation,会导致组件之间样式污染
有哪些 build-in 的样式选择器?
?
:host用于选中当前组件ng-deep会让class变成全局属性,影响到其他组件,通常会在前面添加:host将其限制在该组件和其子组件中:host-context(.css)会限制 css 应用范围在当前宿主组件中
Angular Injectable Service In Depth
Angular 中如何实现 Http 请求
?
Angular 中自带了 httpClient+ RxJS 用于网络请求,并且build-in指令asyc可以将Observable对象转为实际元素,如下:
1 | export class AppComponent implements OnInit { |
Angular 的 Service 适合什么场景?
?
- 数据共享,例如 Redux,可以通过
public来共享变量,也可以通过Observerble来观察数据变化 - 业务逻辑
- API交互
- 状态管理,帮助和跟踪应用程序的状态变化
Angular Dependency Injection In Depth
Angular 中 DI 有什么好处?
?
- 方便 Mock 对应的依赖,特别是在测试环境下,例如:模拟网络请求
- 单例模式,使用工厂模式,可以自定义工厂
Angular 中怎么使用自定义工厂?
?
1 | // Complex |
Angular DI 的 Provider 作用?
?
如果当前组件需要自定义 Provider,那么生成的这个service的生命周期将会和组件绑定。如果不想影响全局其他的该service,则可以使用自定义Provider的方式。
Angular DI 的 shakeable provider 怎么实现?
?
如果直接使用 new InjectionToken(TOKEN) 的方式生成的元素会默认打包到最后的 js 文件中,通过传入第二个参数,指定 factory,这样只有使用了才会打包对应的配置文件
Angular DI 中的 @Host, @Self, @Skipself, Optional 有什么作用
?
- 当 Director 需要所绑定的组件提供依赖的时候,可以通过
host来指定 - 当组件需要自身提供依赖实例的时候,可以使用
Self - 当组件需要父级组件提供依赖实例的时候,可以使用
SkipSelf - 当不确定是否有父级组件提供依赖实例的时候,可以使用
Optional
Angular Change Detection
Angular 的 change detection 是怎样的
?
Angular 有两种 change detection,一种是 Default,也被称为 CheckAlways,即任何可能导致视图发生变化的行为(输入、点击、事件等)触发时,会检查当前组件以及子组件是否发生变化,因此可能会导致出现部分性能损耗。
另一个方式是 OnPush,当组件的输入属性,即@Input发生变化时;当组件事件发生时;当手动调用ChangeDetectorRef.markForCheck()时,才会对比视图是否发生变化,但是需要注意的是对比@Input时是浅对比,不是深对比。使用 OnPush 需要注意,如果有 Observerble 属性的对象,那么需要通过在 template 中添加 async的方式来渲染,如果只在 .ts文件中通过订阅赋值的方式,则页面不会变化。
Angular 中还有什么方法可以避免更新检测
?
如果某个属性传入后不会发生变化,那么可以使用 attribute decorator来指定,可以避免后续变化的更新检测。也可以手动通过调用 ChangeDetectorRef.markForCheck() 来触发检测。
1 | constructor( |
Angular lifecycle hook
Angular 生命周期的执行顺序是什么
?
1. constructor: 注入依赖,进行实例化
2. ngOnChanges: 当被绑定的输入属性(@Input)发生变化时调用,首次绑定时也会调用。
3. ngOnInit: 在组件初始化完成后立即调用,用于初始化数据和执行逻辑。
4. ngDoCheck: 在每个变更检测周期中调用,用于自定义的变更检测逻辑。
5. ngAfterContentInit: 在组件内容投影完成后调用。
6. ngAfterContentChecked: 在每个内容投影完成后调用。
7. ngAfterViewInit: 在组件的视图初始化完成后调用。
8. ngAfterViewChecked: 在每个视图检测周期后调用。
9. ngOnDestroy: 在组件被销毁前调用,用于清理资源和取消订阅。
Angular Partial Template Loading
如何让 Angular 延迟加载
?@defer 装饰器会让对应的组件延迟加载,配合 @placeholder(minimum 3s) 可以实现延时加载的效果