2018 年 22 个 Angular 专家面试问题及答案
这份终极 Angular 高级及专家级面试题清单,可用于招聘新团队成员、自我测试、嘲讽开发主管,或干脆直接忽略。题目来源于khan4019/angular-interview-questions ,并在FullStack.Cafe上解答。
Q1:NgModule 中的“声明”、“提供者”和“导入”有什么区别?
主题:Angular
难度:⭐⭐⭐
imports
使其他模块的导出声明在当前模块中可用declarations
使当前模块中的指令(包括组件和管道)可供当前模块中的其他指令使用。指令、组件或管道的选择器只有在声明或导入后才会与 HTML 匹配。providers
是为了让 DI 知道服务和值。它们被添加到根作用域,并被注入到依赖它们的其他服务或指令中。
一种特殊情况providers
是延迟加载模块具有自己的子注入器。providers
延迟加载模块的默认设置仅提供给该延迟加载模块(而不是像其他模块那样提供给整个应用程序)。
🔗来源: medium.com
Q2:解释“构造函数”和“ngOnInit”之间的区别
主题:Angular
难度:⭐⭐⭐
- 这
Constructor
是类的默认方法,在实例化类时执行,并确保正确初始化类及其子类中的字段。 ngOnInit
是 Angular 调用的一个生命周期钩子,用于指示 Angular 已完成组件的创建。为了使用这个钩子,我们必须导入 OnInit 接口(实际上,实现 OnInit 接口并非强制要求,但被认为是一种良好做法)。
我们主要使用ngOnInit
构造函数进行所有初始化/声明,并避免在构造函数中执行任何操作。构造函数应该仅用于初始化类成员,而不应执行实际的“工作”。
🔗来源: stackoverflow.com
Q3:Angular 6 有什么新功能,为什么我们要升级到它?
主题:Angular
难度:⭐⭐⭐
- Angular Elements - Angular Elements 是一个项目,它允许您将 Angular 组件包装为 Web 组件并将其嵌入到非 Angular 应用程序中。
- 新的渲染引擎:Ivy - 提高速度并减小应用程序大小。
- 可摇树的提供程序- 一种新的、推荐的注册提供程序的方法,直接在 @Injectable() 装饰器中使用新
providedIn
属性 - RxJS 6 - Angular 6 现在内部使用 RxJS 6,因此需要您也更新应用程序。RxJS 发布了一个名为 rxjs-compat 的库,即使您或您正在使用的某个库仍在使用“旧”语法,它也允许您将 RxJS 升级到 6.0 版本。
- ElementRef
<T>
- 在 Angular 5.0 或更早版本中,其 nativeElement 属性的类型为 any。在 Angular 6.0 中,现在可以更严格地定义 ElementRef 的类型。 - 动画- 除非您使用 AnimationBuilder,否则 polyfill web-animations-js 对于 Angular 6.0 中的动画来说不再是必需的。
- i18n——可以拥有“运行时 i18n”,而无需为每个语言环境构建一次应用程序。
🔗资料来源: ninja-squad.com
Q4:什么是AOT?
主题:Angular
难度:⭐⭐⭐
Angular 的 AOT 编译器会在构建过程中预编译应用程序组件及其模板。
使用 AOT 编译的应用程序启动速度更快,原因如下。
- 应用程序组件立即执行,无需客户端编译。
- 模板作为代码嵌入在其组件中,因此客户端不需要模板文件请求。
- 您不需要下载 Angular 编译器,因为它本身就很大。
- 编译器会丢弃未使用的 Angular 指令,然后摇树工具可以将其排除。
🔗来源: stackoverflow.com
Q5:为什么要使用渲染器方法而不是使用原生元素方法?
主题:Angular
难度:⭐⭐⭐⭐
Angular 是一个平台,浏览器只是我们渲染应用的一种选择。当我们直接访问原生元素时,我们放弃了 Angular 的 DOM 抽象,也失去了在非 DOM 环境中执行的机会,例如:
- 原生移动端,
- 原生桌面,
- 网络工作者
- 服务器端渲染。
该类Renderer2
是 Angular 以服务形式提供的一种抽象,它允许你操作应用的元素而无需直接接触 DOM。我们推荐使用这种方式,因为它可以更轻松地开发那些能够在无法访问 DOM 的环境中渲染的应用,例如在服务器、Web Worker 或原生移动设备上。
🔗资料来源: alligator.io
Q6:Angular 中的 Zone 是什么?
主题:Angular
难度:⭐⭐⭐⭐
NgZone
是一个包装器,Zone.js
它是一个库,它围绕异步函数创建上下文,以便使其可跟踪。Angular 的变化检测严重依赖于 Zones。
🔗来源: stackoverflow.com
Q7:为什么要在 Angular 应用中使用延迟加载模块?
主题:Angular
难度:⭐⭐⭐⭐
要延迟加载功能模块,我们需要使用loadChildren
路由配置中的属性来加载它,并且该功能模块不能导入到应用程序模块中。当应用程序规模不断增长时,延迟加载非常有用。在延迟加载模式下,功能模块将按需加载,因此应用程序的启动速度会更快。
const routes: Routes = [
{
path: 'customers',
loadChildren: 'app/customers/customers.module#CustomersModule'
},
{
path: 'orders',
loadChildren: 'app/orders/orders.module#OrdersModule'
},
{
path: '',
redirectTo: '',
pathMatch: 'full'
}
];
🔗资料来源: concretepage.com
Q8:组件和指令的生命周期钩子是什么?
主题:Angular
难度:⭐⭐⭐⭐
Angular 中的组件具有生命周期,即从诞生到消亡的一系列不同阶段。我们可以深入这些不同阶段,从而对应用程序进行更细粒度的控制。
- 构造函数当 Angular 通过在类上调用 new 来创建组件或指令时,会调用此构造函数。
- ngOnChanges每次组件的输入属性之一发生变化时调用。
- ngOnInit:当指定组件初始化完成后调用。此钩子仅在第一个 ngOnChanges 之后调用一次。
- ** ngDoCheck** 当指定组件的变更检测器被调用时调用。它允许我们为指定组件实现自己的变更检测算法。
- ngOnDestroy该方法将在 Angular 销毁组件之前调用。使用此钩子可以取消订阅可观察对象并分离事件处理程序,以避免内存泄漏。
这些钩子仅针对组件调用,而不针对指令调用。
- ngAfterContentInit在 Angular 将任何内容投影到组件视图后调用(有关更多信息,请参阅上一节关于内容投影的讲座)。
- ngAfterContentChecked每次通过 Angular 的变化检测机制检查给定组件的内容时调用。
- ngAfterViewInit当组件的视图已完全初始化时调用。
- ngAfterViewChecked每次通过 Angular 的变化检测机制检查给定组件的视图时调用。
🔗来源: codecraft.tv
Q9:如何从准备好的 TemplateRef 插入嵌入视图?
主题:Angular
难度:⭐⭐⭐⭐
您可以使用方法创建嵌入视图,createEmbeddedView
然后通过以下方式将该视图附加到 DOM TemplateRef
:
@Component({
selector: 'app-root',
template: `
<ng-template #template let-name='fromContext'><div>{{name}}</ng-template>
`
})
export class AppComponent implements AfterViewChecked {
@ViewChild('template', { read: TemplateRef }) _template: TemplateRef<any>;
constructor() { }
ngAfterViewChecked() {
this.vc.createEmbeddedView(this._template, {fromContext: 'John'});
}
}
🔗来源: stackoverflow.com
Q10:如何检测 Angular 中的路线变化?
主题:Angular
难度:⭐⭐⭐⭐
在 Angular 中,你可以subscribe
将 Rx 事件传递给 Router 实例。因此你可以执行以下操作:
class MyClass {
constructor(private router: Router) {
router.subscribe((val) => /*whatever*/ )
}
}
🔗来源: medium.com
Q11:即时(JIT)编译器一般做什么?
主题:Angular
难度:⭐⭐⭐⭐
JIT 编译器在程序启动后运行,并将代码(通常是字节码或某种虚拟机指令)即时(或称为“即时”)编译为通常更快的形式,通常是主机 CPU 的原生指令集。JIT 可以访问动态运行时信息,而标准编译器则无法访问这些信息,因此可以进行更好的优化,例如内联常用函数。
这与传统编译器形成对比,传统编译器在程序首次运行之前将所有代码编译为机器语言。
🔗来源: stackoverflow.com
问题 12:如何创建使用 scss 的应用程序?Angular 6 有什么变化?
主题:Angular
难度:⭐⭐⭐⭐
这是 CLI v1.x 中的样式配置在 .angular-cli.json 文件中的样子。
"defaults": {
"styleExt": "scss",
"component": {}
}
但是,如果你查看版本 6 中 angular.json 文件的配置模式,你将不再找到这个配置。要使用 SCSS,只需在项目级别的 angular.json 文件中导入 scss 文件(默认值为“src/styles.scss”),如下所示。
{
...
projects: {
[your_project_name]: {
...
architect: {
build: {
...
options: {
styles:{
"src/styles.scss"
}
}
}
}
}
}
}
🔗来源: medium.com
Q13:什么是 ngUpgrage?
主题:Angular
难度:⭐⭐⭐⭐
NgUpgrade是由 Angular 团队整合的一个库,我们可以在我们的应用程序中使用它来混合和匹配 AngularJS 和 Angular 组件,并桥接 AngularJS 和 Angular 依赖注入系统。
🔗来源: blog.nrwl.io
Q14:什么是反应式编程,它与 Angular 有何关系?
主题:Angular
难度:⭐⭐⭐⭐
响应式编程是使用异步数据流进行编程。RxJs 是 JavaScript 的响应式扩展 (Reactive Extensions for Javascript) 的缩写,它是 JavaScript 可观察对象 (Observables) 的一个实现。可观察对象类似于流 (Stream)(在许多语言中),允许传递零个或多个事件,每个事件都会调用回调函数。Angular 目前以两种不同的方式使用 RxJs 可观察对象:
- 作为内部实现机制,实现一些核心逻辑,如
EventEmitter
- 作为其公共 API 的一部分,
Forms
即HTTP module
即使您不了解响应式编程或 RxJS,也能使用 Angular 构建最复杂的应用程序。然而,它可以让某些类型的应用程序更易于架构。
Q15:列举一些 Angular 中的安全最佳实践
主题:Angular
难度:⭐⭐⭐⭐
- 为了系统地阻止 XSS 错误,Angular 默认将所有值视为不受信任(清理)
- Angular 模板与可执行代码相同:模板中的 HTML、属性和绑定表达式(但不包括绑定的值)都被认为是安全的。为了防止这些漏洞,请使用离线模板编译器(也称为模板注入)。
- 避免直接与 DOM 交互,而是尽可能使用 Angular 模板。
- 将模板代码注入 Angular 应用程序与将可执行代码注入应用程序相同。因此,请验证服务器端代码中的所有数据,并进行适当的转义,以防止服务器上的 XSS 漏洞。
- Angular HttpClient 提供内置支持以防止客户端的 XSRF 攻击。
- 服务器可以通过在所有 JSON 响应中添加前缀来防止 XSSI 攻击,使其按照惯例不可执行,即使用众所周知的字符串
")]}',\n"
。Angular库可以识别此约定,并在进一步解析之前HttpClient
自动从所有响应中删除该字符串。")]}',\n"
Q16:我可以将 jQuery 与 Angular 一起使用吗?
主题:Angular
难度:⭐⭐⭐⭐
首先使用 npm 安装 jQuery,如下所示
npm install jquery — save
其次,转到./angular-cli.json
Angular CLI 项目文件夹根目录下的文件,找到scripts: [] property
,并包含 jQuery 的路径,如下所示
“scripts”: [ “../node_modules/jquery/dist/jquery.min.js” ]
现在,要在应用程序的任何地方使用 jQuery,您只需在app.component.ts
文件中按如下所示导入它。
import * as $ from ‘jquery’;
考虑:
import { Component, OnInit } from '@angular/core';
import * as $ from 'jquery';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'Look jQuery Animation working in action!';
public ngOnInit()
{
$(document).ready(function(){
$("button").click(function(){
var div = $("div");
div.animate({left: '100px'}, "slow");
div.animate({fontSize: '5em'}, "slow");
});
});
}
}
🔗来源: medium.com
Q17:Angular 中与 AngularJS“$watch”等效的是什么?
主题:Angular
难度:⭐⭐⭐⭐⭐
解决方案是set
ES6 中的语法。该set
语法将对象属性绑定到一个函数,当尝试设置该属性时,该函数将被调用。
import { Component, Input } from '@angular/core';
@Component({
selector: 'example-component',
})
export class ExampleComponent {
public internalVal = null;
constructor() {}
@Input('externalVal')
set updateInternalVal(externalVal) {
this.internalVal = externalVal;
}
}
🔗来源: medium.com
Q18:即时编译 (JiT) 与提前编译 (AoT)。解释一下它们的区别。
主题:Angular
难度:⭐⭐⭐⭐⭐
JIT——在执行 TypeScript 时及时编译它:
- 在浏览器中编译。
- 每个文件单独编译。
- 更改代码后和重新加载浏览器页面之前无需构建。
- 适合本地开发。
AOT——在构建阶段编译 TypeScript:
- 由机器本身通过命令行进行编译(更快)。
- 所有代码一起编译,在脚本中内联 HTML/CSS。
- 无需部署编译器(Angular 大小的一半)。
- 更安全,原始来源不公开。
- 适用于生产构建。
🔗来源: stackoverflow.com
Q19:您知道如何并排运行 angularJS 和 angular 吗?
主题:Angular
难度:⭐⭐⭐⭐⭐
为了并行运行这两个框架并使组件可互操作,Angular 项目附带了一个模块ngUpgrade。该模块基本上充当了适配器外观的角色,因此我们实际上并不会感觉到有两个框架并行运行。
为了实现这一点,需要四个要素协同工作:
- 依赖注入 - 将 Angular 服务暴露到 Angular 1.x 组件中,反之亦然。
- 组件嵌套 - Angular 1 指令可以在 Angular 2.x 组件中使用,Angular 2.x 组件也可以使用 Angular 1 指令
- 内容投影/包含 - Angular 1 组件包含 Angular 2.x 组件,Angular 2.x 组件项目 Angular 1 指令
- 变化检测 - Angular 1 范围摘要和 Angular >= 2.x 中的变化检测器是交错的
典型的升级过程如下:
- 包含 Angular 和升级模块
- 选择要升级的组件并更改其控制器和模板 Angular 2.x 语法(现在这是一个 Angular 2.x 组件)
- 降级 Angular 2.x 组件以使其在 Angular 1.x 应用中运行
- 选择要升级的服务,这通常需要很少的改变(特别是如果我们使用 ES2015)
- 重复步骤 2 和 3(和 4)
- 将 Angular 1 bootstrap 替换为 Angular 2.x bootstrap
🔗来源: blog.thoughtram.io
Q20:您能提供一些使用 ngZone 的具体示例吗?
主题:Angular
难度:⭐⭐⭐⭐⭐
当您想要使用时会有很多情况NgZone
,我可以举两个例子:
- 当你想在 Angular 的变化检测之外运行某些操作时。比如说,我们想在用户滚动时进行一些计算,但又不想运行变化检测,那么你可以使用 NgZone:
constructor(private zone:NgZone){
this.zone.runOutsideOfAngular(()=>{
window.onscroll = ()=>{
// do some heavy calculation :
}
})
}
- 与上述情况完全相反,你有一个函数,它以某种方式位于 Angular 区域之外,而你希望它位于其中,就像当第三方库为你做一些事情时,你希望它绑定到你的 Angular 循环中。
this.zone.run(()=>{
$.get('someUrl').then(()=>{
this.myViewVariable = "updated";
})
});
🔗来源: stackoverflow.com
Q21:为什么angular需要使用url段?
主题:Angular
难度:⭐⭐⭐⭐⭐
UrlSegment是 URL中两个斜杠之间的部分。它包含与该段相关的路径和矩阵参数。
矩阵参数与路径段绑定,而查询参数与 URL 绑定。它们具有不同的语义。
考虑:
localhost:3000/heroes;id=15;foo=foo/bar/baz
// instead of localhost:3000/heroes/bar/baz?id=15&foo=foo
这些参数与 heroes和 URL 绑定。当你访问 route.url 时,你会看到以下内容:
this.route.url.subscribe((url: UrlSegment[]) => {
let heroes = url[0];
let heroesMatrix = heroes.parameters();
// heroes should contain id=15, foo=foo
let bar = url[1].path; // 15
let baz = url[2].path; //foo
})
对于矩阵参数,您还可以订阅 params,而不是将它们从 url 中剥离出来。
this.paramSubscription = this.activeRoute.params.subscribe(params => {
const bar = params['bar'];
const baz = params['baz'];
});
对于 Angular 应用来说,真正关心这些参数的只有我们开发者。用户并不关心。它不是一个 REST API,我们不应该遵循众所周知的语义。对于我们的 Angular 应用来说,只要我们开发者知道如何使用参数(无论是矩阵还是查询),使用哪个参数都无所谓。
🔗来源: https://stackoverflow.com
Q22:何时使用查询参数而不是矩阵参数?
主题:Angular
难度:⭐⭐⭐⭐⭐
- 查询参数:http://example.com/apples ?order=random&color=blue
- 矩阵参数:http://example.com/apples;order=random ;color=blue
矩阵参数和查询参数之间的差异不仅仅是约定。
主要区别在于:
- 带有查询参数的 URL 的响应不会被中介/代理缓存(目前)
- 矩阵参数可以出现在路径中的任何位置
- 计算相对 uri 是不同的
- 查询参数通常被滥用来添加新动词,而不是使用资源上的现有方法
- 矩阵参数不是资源,它们是帮助引用信息空间中难以在层次结构中表示的资源的方面
🔗来源: stackoverflow.com
文章来源:https://dev.to/aershov24/22-expert-angular-interview-questions-and-answers-in-2018-1m1g感谢🙌的阅读,祝你面试顺利!
更多 FullStack 面试问答,请访问👉 www.fullstack.cafe