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)
可以实现延时加载的效果