布莱恩F爱
向来自波特兰的谷歌开发者专yobet英雄联盟家学习Angular、Web技术和Node.js。
广告 ·ultimatecourses.com
使用Ultimate Courses以正确的方式学习Angular"></a>
          </div>
          <article class=

Angular 9更新指南

学习如何成功升级到Angular版本9。

先决条件

在你开始用新的Ivy渲染器更新到Angular版本9之前,有几个先决条件你需要完成:

  1. NgForm选择器。
  2. @ContentChild@ContentChildren主机。
  3. 不要给模板变量赋值。
  4. TypeScript编译器更新(可选)。
  5. 渲染器弃用。

让我们逐一分析。

NgForm选择器

首先,更新所有NgForm的选择器< ng-form >自定义元素。如果您正在使用标准,这并不影响您< >形式元素或响应式表单。

之前:

<ngForm# personFormngForm><mat-form-field><mat-label>搜索mat-label><输入matInput((ngModel))的名字/>mat-form-field>ngForm>

为了兼容,您需要从< ngForm >< ng-form >

<ng-form# personFormngForm><mat-form-field><mat-label>搜索mat-label><输入matInput((ngModel))的名字/>mat-form-field>ng-form>

@ContentChild@ContentChildren主机

@ContentChild@ContentChildren装饰器查询将不再能够匹配指令自己的主机节点。

之前:

指令选择器“[swrActions]”出口ActionsDirective实现了AfterContentInit// [TODO]: Angular v9 ContentChild不会返回宿主元素!!ContentChildActionsDirective静态真正的ElementRefselfElementRefElementRef构造函数私人只读的渲染器Renderer2ngAfterContentInit常量埃尔selfElementRefnativeElement作为HTMLElement如果埃尔返回渲染器setStyle埃尔“显示”“弯曲”渲染器setStyle埃尔“flexDirection”“行”渲染器setStyle埃尔“justifyContent”“flex-end”

上面,我们使用的是@ContentChild内容查询访问主机ElementRef的指令。FWIW,这不是一个最佳实践,这就是为什么它被弃用。

理想情况下,我们正在访问ElementRef通过注入到指令中的依赖项:

指令选择器“[swrActions]”出口ActionsDirective实现了AfterContentInit构造函数私人只读的elementRefElementRef私人只读的渲染器Renderer2ngAfterContentInit常量埃尔elementRefnativeElement作为HTMLElement如果埃尔返回渲染器setStyle埃尔“显示”“弯曲”渲染器setStyle埃尔“flexDirection”“行”渲染器setStyle埃尔“justifyContent”“flex-end”

这里的目标是避免使用@ContentChild ()@ContentChildren ()访问主机元素的查询。迁移依赖于注入宿主的ElementRef

不要给模板变量赋值

这种迁移是必要的,以避免突变和为对象分配未知属性。

其中的一个Angular版本9中带有新的Ivy渲染器的更新是模板类型检查,这与这个新功能直接相关。在Angular版本9和Ivy渲染器之前,模板变量基本上是一个任何类型。这意味着,您可以根据需要修改对象及其属性。一般来说,这是一个反模式。

在Angular 9版和Ivy渲染器中,为了严格检查模板类型,仅模板变量将基于TypeScript编译器选项被强类型化。因此,我们必须突变模板只变量。

让我们看一个例子突变模板只变量:

<按钮# translateBtn(点击)translateBtn。翻译=!translateBtn。翻译>翻译按钮><mat-accordion><mat-expansion-panel* ngFor让人的><mat-expansion-panel-header><mat-panel-title>{{person.fields.name | wookiee: translateBtn。翻译}}mat-panel-title>mat-expansion-panel-header>mat-expansion-panel>mat-accordion>

translateBtn在Angular版本8中,只使用模板的变量是type任何.在Angular版本9中,该变量被强类型定义为HTMLButtonElement.和,HTMLButtonElement接口有一个翻译财产。

我们的目标是去除模板变量的突变,并依赖于组件的属性和方法:

<按钮(点击)ontTranslate ()>翻译按钮><mat-accordion><mat-expansion-panel* ngFor让人的><mat-expansion-panel-header><mat-panel-title>{{person.fields.name | wookiee: translateToWookiee}}mat-panel-title>mat-expansion-panel-header>mat-expansion-panel>mat-accordion>

我们已经删除了只用于模板的变量。请注意模板变量表示法# translateBtn被移除。

现在,我们只需实现组件类中的属性和方法:

出口PeopleListComponent/**如果内容应该翻译为Chewbaka */translateToWookieeonTranslate无效translateToWookieetranslateToWookiee

TypeScript编译器更新(可选)

在升级到Angular版本9之前,你可以选择加入编译器更新,这样你的升级就会更加无缝。更新你的tsconfig.json文件如下:

“compilerOptions”//省略“noImplicitAny”真正的“noImplicitReturns”真正的“noImplicitThis”真正的“noFallthroughCasesInSwitch”真正的“strictNullChecks”真正的//省略

要包含的关键编译器标志有:

  • noImplicitAny防止编译器暗示实参、变量或赋值的类型是类型任何,当编译器不能推断出类型或代码没有显式声明类型时,默认值为。
  • noImplicitReturns防止你在不被注意的情况下,从一个函数到最后,意思是在你不知道函数的情况下可以返回任何隐式。这可以确保您正确地返回正确的类型,无论您在代码的哪个分支中返回值。
  • noImplicitThis确保我们不会假设的价值.作为JavaScript开发人员,我们知道值取决于函数的执行上下文。这个编译器标志防止我们假设或允许编译器暗示的上下文
  • noFallthroughCasesInSwitch确保每一个情况下语句由适当的打破为了防止案子落到情况下声明。
  • strictNullChecks确保我们不允许两者兼而有之未定义的除非在TypeScript中显式声明,否则不能全局可用或可赋值。这个标志是高度推荐,因为它可以防止可能导致的错误nullish合并和其他真实/虚假的胁迫。

渲染器弃用

人们对这一改变期待已久,因此这并不令人意外。弃用的渲染器最终被从Angular代码库中移除。这意味着如果你的Angular项目通过依赖注入依赖于已弃用的组件渲染器类,您需要迁移到它Renderer2

幸运的是,这种迁移被ng更新我们马上要执行的命令。所以,如果你很懒(像我一样),那么你现在可以跳过这个,让Angular更新为你迁移这个。

大多数方法都很容易更新渲染器Renderer2,其余的必为你们修理。

确保在更新后查看git diff渲染器Renderer2迁移。

更新到最新的Angular 8补丁

在你升级到Angular版本9之前,你必须先升级到Angular版本8的最新稳定版本:

更新@angular/core@8 @angular/cli@8

更新到Angular版本9

我们成功了!我们准备通过以下方式将Angular项目升级到Angular版本9ng更新

更新@angular/cli @angular/core

虽然发布还不是最终版本,并且目前处于发布候选阶段,但您需要附加——下一个国旗:

Ng update @angular/cli @angular/core——next

本地化(i18n)

如果你正在使用Angular的本地化(i18n)框架,那么你还需要使用ng添加命令安装一个新的@angular /本地化包:

ng添加@angular /本地化

当你检查angular.json文件更新后,您还会注意到一个新的i18n配置部分:

“美元模式””。/ node_modules / @angular / cli / lib / config / schema.json”“版本”1“newProjectRoot”“项目”“项目”“angular-v9”“国际化”“场所”“德”“翻译”“src /地区/ messages.de.xlf”“baseHref”""

你的angular.json您应该考虑的配置。

首先,指定sourceLocal财产。默认值是en - us,所以你需要根据源代码的区域设置为你的应用程序指定源区域设置:

“美元模式””。/ node_modules / @angular / cli / lib / config / schema.json”“版本”1“newProjectRoot”“项目”“项目”“angular-v9”“国际化”“sourceLocale”“en - us”“场所”“德”“翻译”“src /地区/ messages.de.xlf”“baseHref”""

其次,考虑更新baseHref根据您的需要为每个地区配置。在大多数情况下,我们将使用惟一的子域或惟一的路径为应用程序的每个地区提供服务。

在我的用例中,我希望每个区域设置在唯一的路径上:

  • 我们英语:/ en - US /
  • 多伊奇:/德/

因此,我修改了baseHref地区:

“美元模式””。/ node_modules / @angular / cli / lib / config / schema.json”“版本”1“newProjectRoot”“项目”“项目”“angular-v9”“国际化”“sourceLocale”“en - us”“场所”“德”“翻译”“src /地区/ messages.de.xlf”“baseHref”“/ /”

接下来,我的Angular版本8项目为每个地区使用了多个构建配置。根据我目前的经验,你可以删除这些,因为它们不再需要:

“美元模式””。/ node_modules / @angular / cli / lib / config / schema.json”“版本”1“newProjectRoot”“项目”“项目”“angular-v9”...“架构师”“构建”...“配置”“德”...“production-de”...

我把两个production-de配置。

最后,更新项目中的生产构建命令package.json文件以包含新的——本地化创建所有本地化的标志:

“名称”“angular-v9”“版本”“0.0.0”“脚本”“ng”“ng”...“服务:dist ""http-server -p 8080 -c-1 dist/angular-v9"“构建”"ng build——prod——本地化"

注意:

  • 首先,我有一个新的服务:经销命令,使用http-server Node模块提供本地化版本的生产构建。
  • 第二,我更新了构建命令以包含新的——本地化标记以构建所有本地化。

我还要提一下,您可以创建额外的配置来构建特定的区域设置或一组区域设置。

更新后的清单

在我们成功地更新到Angular版本9之后,有两件小事需要我们去做:

  1. 从已弃用的迁移TestBed.get ()方法的新TestBed.inject T < > ()方法。
  2. 删除不必要的entryComponents在我们的属性@NgModule ()装饰器对象。

迁移到TestBed.inject ()

发布了Angular版本9的更新后,我们的第一个任务就是进行迁移TestBed.get ()TestBed.inject T < > ()

之前:

描述“FilmService”=>服务FilmServicebeforeEach=>试验台configureTestingModule进口HttpClientTestingModule“创建”=>服务试验台得到FilmService预计服务toBeTruthy

后:

描述“FilmService”=>服务FilmServicebeforeEach=>试验台configureTestingModule进口HttpClientTestingModule“创建”=>服务试验台注入<FilmService>FilmService预计服务toBeTruthy

注意:

  • 我们改变TestBed.get ()TestBed.inject T < > ()
  • 属性返回的类型的泛型注入()方法。

删除entryComponents

有了Angular版本9和新的Ivy渲染器,我们不再需要显式地向编译器指示组件依赖图之外的组件。中需要声明的组件的一个很好的例子entryComponents数组是对话框。

这个更新很简单,谁不喜欢删除代码呢。只是删除entryComponents数组的@NgModule ()应用程序中的装饰器。

之前:

NgModule声明//省略PersonFilmsDialogComponentPersonHomePlanetDialogComponententryComponentsPersonFilmsDialogComponentPersonHomePlanetDialogComponent出口PeopleModule

在我们移除不必要的东西之后entryComponents数组:

NgModule声明//省略PersonFilmsDialogComponentPersonHomePlanetDialogComponent出口PeopleModule

成功!

我们已经成功地更新到了Angular 9版和新的Ivy渲染引擎。

有问题吗?需要帮忙吗?让我知道!

布莱恩F爱

嗨,我是布莱恩。我对TypeScript、Angular和Node.js感兴趣。我和我最好的朋友邦妮结婚了,我住在波特兰,我经常滑雪。