Angular 8版本的新功能

因此,Angular 8出现了,它包括常春藤预览,对服务人员的支持,不同的负载以及其他一些修饰。 Manfred Steyer解释了最新版本中最重要的更改。

按照计划,没有什么奇怪的:可以使用ng update来完成框架和CLI的更新,而新功能是“座右铭,而不是革命”的座右铭。

在本文中,作者讨论了Angular 8和Angular CLI 8的最重要的新功能。本文中使用的示例可在GitHub找到

下切:


  • 首先看看常春藤
  • 网络工作者
  • 差分加载
  • 延迟加载模块
  • ViewChild和ContentChild的重大更改
  • 新功能ngUpgrade


首先看看常春藤


Angular社区正在等待的下一个重大新闻是Ivy,新的编译器以及新的渲染引擎。 Ivy可以生成更小的束,增量编译,并且是Angular未来创新的基础。

由于Angular的许多基本部分都已更改,因此Angular团队特别注意与以前版本的兼容性:升级到Ivy后,现有应用程序应以与以前相同的方式工作。 充其量,您将获得更小的捆绑包。 这并不是无私的,因为Google上有600多个应用程序正式基于Angular-传闻实际数字要高得多。

对于Angular 8,可以使用Ivy的初步版本进行测试。 此版本的目的是获得快速反馈。 因此,角度小组建议不要立即在产品中使用Ivy,而应继续使用经典视图引擎(图1)。


得益于差异加载(如下所示),现在可以优化捆绑包大小。

根据谷歌Angular团队的首席技术官布拉德·格林(Brad Green)的说法,在ngconf 2019上,Ivy将在兼容模式和差分加载相结合的情况下显着提高包装尺寸。 因此,敢于冒险的人已经可以测试未来的Ivy API。 特别是这种模式具有很大的优化潜力。 该API仍被标记为私有。 查看其类和功能,您可以说:它们以特殊符号begin开头。

如果您已经想尝试Ivy,则可以使用enable-ivy开关创建一个新项目:
ng new ivy-project --enable-ivy 

此项告诉CLI将以下条目保存在tsconfig.app.json配置中:
 "angularCompilerOptions": { "enableIvy": true } 

升级到版本8后,也可以手动添加该条目,以使用Ivy测试现有应用程序。
要以调试模式运行该应用程序,建议使用AOT:
 ng serve --aot 

另外,您应注意使用ng build创建的应用程序的大小。 对于角度9,默认情况下应启用常春藤。 在此之前,Angular团队计划继续努力以确保与旧版本的兼容性。

网络工作者


根据定义,JavaScript是单线程的。 因此,耗时的任务(例如查询数据)通常是异步执行的。 不用说,这对复杂的计算没有帮助。 随着广泛的JavaScript解决方案,它们变得越来越普遍,因此我们在几乎所有的Web浏览器上都支持Web Worker。 这些是浏览器在单独的线程中启动的脚本。 通过消息与浏览器选项卡上的流进行通信。
尽管网络工作者与Angular本身并不相关,但在构建时应将它们考虑在内。 目标是为每个网络工作者提供一个软件包。 新的CLI已完成此任务。
为了演示一个新功能,我将向JavaScript演示所谓的“ n个皇后问题 ”的实现。该想法是将一个皇后连续放置在棋盘上,而又不会互相威胁。相同的行,列或对角线不应再成为女王。

用于计算棋盘上所有可能解的算法被认为计算复杂。 尽管对于常规的八行和八列国际象棋棋盘的计算速度非常快,但是常规计算机已经达到了12 x 12棋盘的极限,目前的记录是27 x 27棋盘的解决方案。 为此,使用了俄罗斯超级计算机。
为了将此计算转换为背景,我们必须首先使用CLI创建一个Web worker:
 ng generate worker n-queens 

该指令不仅为员工创建文件,而且为构建过程所需的配置文件和现有文件中的条目创建文件。 如果同一文件夹包含名称相同且扩展名为.component.ts的组件,则CLI还将添加代码以与Web Worker交互。
工作程序本身由事件的侦听器组成:
 import nQueens from './n-queens'; addEventListener('message', ({ data }) => { const result = nQueens(data.count); postMessage(result, undefined); }); 

当主线程向工作程序发送消息时,将执行该事件。 该参数包含从主流发送的信息。 在这种情况下,它受count属性的限制,该属性设置棋盘的大小。 在评估nQueens函数(在此省略)之后,eventListener通过postMessage将结果发送回主线程。 因此,浏览器将触发消息事件。
在using组件中使用Worker类与工作脚本进行交互:
 const count = parseInt(this.count, 10); const worker = new Worker('../logic/n-queens.worker', { type: 'module' // Worker uses EcmaScript modules }); worker.postMessage({count}); worker.addEventListener('message', (event) => { // tslint:disable-next-line: no-console console.debug('worker result', event.data); // Update chessboard this.processResult(event.data); }); 

该组件通过postMessage向工作人员发送具有所需棋盘大小的消息,从而从那里开始计算。 它通过消息事件接收结果。
将来,CLI会注意正确组装工作程序脚本。 TypeScript编译器在.worker.ts的末尾识别它们,该文件在ng generate worker命令创建的tsconfig.worker.json中注册。 为了确保在构建主应用程序时CLI不会再次影响这些文件, ng generate worker将相同的文件模板放在tsconfig.app.json的exclude部分中。
完整的实现在项目中有作者的例子。 为了进行比较,可以在主线程和Web Worker中解决N个皇后区任务的示例。 例如,当您尝试解决12 x 12棋盘的问题时,您会看到UI在第一种情况下挂起,而使用Web Worker进行后台计算不会降低性能。

差分加载


到目前为止,习惯将应用程序编译为较旧的ES 5,因为此版本的“我们父亲的JavaScript”几乎可以在任何地方使用。 这意味着IE11和Google的网络抓取工具都可以执行此代码。
但是,新的ES 2015及其后续版本效率更高:它们允许您创建更紧凑的程序包,浏览器也可以更有效地解释它们。 由于以前习惯以回滚到ES 5作为最小公分母,因此不幸的是,现代浏览器无法利用该语言的新版本。
现在结束了:从版本8开始,CLI具有称为差异加载的功能。 这个想法是提供两组软件包:一组基于ECMAScript 5并为较旧的浏览器设计,另一组基于新版本的ECMAScript(例如ECMAScript 2015),并为现代浏览器提供上述好处。
您无需进行大量工作即可启用差异加载:只需设置受支持的ECMAScript版本的上限和下限即可。 tsconfig.json中指示上限,如下所示:
 "target": "es2015" 

下限是在browserslist文件中定义的。 该文件包括将根据某些标准(例如市场份额)支持的浏览器。 可以将它们保存在例如browserslist文件中,该文件是CLI在创建新项目时在项目根目录中创建的:
> 0.5%
last 2 versions
Firefox ESR
not dead
IE 9-11

在这种情况下,浏览器列表包括带有IE 9-11条目的ES 5浏览器。 因此,CLI将较低的阈值定义为此版本。 当CLI收到ng build命令时,将在两个版本上运行构建过程:

此过程的缺点是:组装所需的时间加倍。
浏览器现在可以决定要下载哪个版本的软件包。 为此,他们获得了index.html加载项中脚本的链接:指向ECMAScript 5软件包的用户将获得一个nomodule。 因此,具有ECMAScript支持以及ECMAScript 2015+支持的浏览器将不会忽略此脚本。 另一方面,ECMAScript 2015+软件包是由CLI以type =“ module”实现的。 因此,较旧的浏览器将忽略以下脚本:
 <script src="main-es2015.js" type="module"></script> <script src="main-es5.js" nomodule></script> 

与ng build不同,其余CLI命令仅使用(!)ES支持的上限。 在我们的例子中,这是ECMAScript2015。这是出于效率方面的原因:在调试和测试期间,开发人员通常希望尽快看到结果,而无需等待第二个构建。

延迟加载模块


从头几天开始,Angular路由器就支持延迟加载。 到目前为止,这是通过可加载模块的神奇定义实现的:
 { path: 'lazy', loadChildren: () => './lazy/lazy.module#LayzModule' } 

#之前的值描述了通往模块实现文件的路径; after的值表示其中包含的类。 此描述样式可在Angular 8中使用,但相对于ECMAScript动态导入已弃用:
 { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) } 

新记录选项仍包含文件名作为魔术值。 但是,由于许多IDE支持导入,因此无效值将立即返回错误。

ViewChild和ContentChild的重大更改


对ViewChild和ContentChild的使用进行了重要的更改,但不幸的是,过去这些更改并非总是可以预期的。 如果在较早的版本中,组件将它们用于查询结构指令内的元素(例如ngIf或ngFor),则ngOnInit中已经提供了查询结果。 否则,我们只能在ngAfterViewInit(或ContentChild的ngAfterContentInit)之前访问它们。 对于后来由于数据绑定而加载到DOM中的元素,程序代码应具有ngAfterViewChecked或相应的ngAfterContentChecked。
由于此行为令人困惑,因此该组件现在应指示何时应进行解析:
 @ViewChild('info', { static: false }) paragraph: ElementRef; 

如果静态标志为true,则在初始化组件时Angular会尝试查找元素。 仅当它们不在结构指令中时,此方法才有效。 当使用static:false时,将在初始化或更新视图后执行解析。
ng update会尝试自动输入正确的值,如果无法输入正确的值,它将使用TODO添加注释。
此更改不会影响使用ViewChildren和ContentChildren装饰器的查询。 他们总是具有动态的行为,用静态的新术语来说是错误的。

新功能ngUpgrade


到目前为止,AngularJS 1.X和Angular与ngUpgrade混合使用的问题之一是这两个框架的路由器由于URL而竞争。 这导致难以解释副作用。 为了避免这种情况,增加了在两个版本中使用单个URL位置服务的功能。
为此,Angular团队扩展了Angular定位服务的功能,从而在AngularJS中提供了$ location的替代品。
因此,已将新的onUrlChange方法添加到定位服务中以跟踪URL更改:
 export class AppComponent { constructor(loc: Location, pLoc: PlatformLocation) { loc.onUrlChange((url) => console.debug('url change', url)); console.debug('hostname: ', pLoc.hostname); } } 

PlatformLocation服务提供对URL特定部分的附加访问。 在此可以找到有关基于$位置替换如何更好地集成框架的详细说明。 此外,您现在可以找到基于上述动态ECMAScript导入的AngularJS延迟加载解决方案。

结论


Angular团队再次信守诺言:过渡到新版本的Angular很简单,并且不包含重大更改。 相反,一些角落被消除了,这使得使用Google的SPA框架的工作更加轻松。 如果旧版浏览器不受支持或由单独的软件包支持,则差异加载为进一步优化软件包大小提供了机会。 对Web worker的支持表明,计算密集型任务在浏览器中找到了处理方式。 爱好者现在可以在常春藤迈出第一步。

PS:这是我的第一篇译文,因此请注意评论,建议和评论中的错误。

Source: https://habr.com/ru/post/zh-CN455493/


All Articles