布莱恩F爱
从专注于角图,Web技术以yobet英雄联盟及波特兰的Node.js的Google开发人员专家中学习。
广告 ·ultimatecourses.com.
用终极课程学习角度正确的方式”></a>
          </div>
          <article class=

Angular 9更新指南

学习如何成功更新到Angular版本9。

先决条件

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

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

让我们逐个分析一下。

NgForm选择器

首先,更新所有NgForm选择器在应用程序中使用自定义元素。如果您正在使用标准,这不会影响您< >形式元素或反应形式。

之前:

<NGForm.#personform.=NGForm.><mat-form-field><mat-label>搜索mat-label><输入matInput[(ngmodel)]=的名字=/>mat-form-field>NGForm.>

为了兼容,您需要从:

<ng-form#personform.=NGForm.><mat-form-field><mat-label>搜索mat-label><输入matInput[(ngmodel)]=的名字=/>mat-form-field>ng-form>

@ContentChild@contentchildren.主持人

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

之前:

@指令({选择器:'[Swractions]'})出口ActionsDirective实现了后intentinit.{// [todo]:Angular V9 ContentChild不会返回主机元素!!@ContentChild.(ActionsDirective,{静态:真正,:Elementref.})自我refref.:Elementref.;构造函数(私人只读的渲染器:Renderer2){}ngAfterContentInit(){常量埃尔=自我refref.母语作为htmlelement.;如果(!埃尔){返回;}渲染器setstyle.(埃尔,'显示','柔性');渲染器setstyle.(埃尔,'flexdirection',“行”);渲染器setstyle.(埃尔,'justifycontent',“flex-end”);}}

以上,我们正在使用@ContentChild内容查询访问主机Elementref.对于指令。FWIW,这不是最好的做法,这就是为什么这是不推荐的。

理想情况下,我们正在访问Elementref.通过注入我们的指令的依赖性:

@指令({选择器:'[Swractions]'})出口ActionsDirective实现了后intentinit.{构造函数(私人只读的Elementref.:Elementref.,私人只读的渲染器:Renderer2){}ngAfterContentInit(){常量埃尔=Elementref.母语作为htmlelement.;如果(!埃尔){返回;}渲染器setstyle.(埃尔,'显示','柔性');渲染器setstyle.(埃尔,'flexdirection',“行”);渲染器setstyle.(埃尔,'justifycontent',“flex-end”);}}

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

不要将值分配给仅模板的变量

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

其中的一个在Angular 9版中,新的Ivy渲染器的更新是模板类型检查,这与这个新功能直接相关。在Angular version 9和Ivy渲染器之前,模板型变量基本上是一个任何类型。这意味着,您可以在适合时突变对象及其属性。一般来说,这是一个反attern。

从Angular第9版和Ivy渲染器开始,仅限模板的变量将根据TypeScript编译器的模板类型检查严格度选项,成为强类型变量。因此,我们必须不要突变模板只变量。

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

<按钮# translateBtn(点击)=translatebtn.translate =!translatebtn.translate>翻译按钮><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与角度版本8的模板 - 仅变量是类型任何。使用角度9,变量被强烈打字为HTMLButtonElement。而且,这HTMLButtonElement接口有一个翻译财产。

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

<按钮(点击)=ontTranslate ()>翻译按钮><mat-accordion><mat-expansion-panel* Ngfor.=让某人做某事><mat-expansion-panel-header><mat-panel-title>{{person.fields.name |wookiee:翻译mat-panel-title>mat-expansion-panel-header>mat-expansion-panel>mat-accordion>

我们已删除了仅模板的变量。注意模板变量表示法# translateBtn已被删除。

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

出口PeopleListComponent.{/**如果内容需要翻译成Chewbaka,则为True */translateToWookiee=;onTranslate():空虚{translateToWookiee=!translateToWookiee;}}

TypeScript编译器更新(可选)

在更新到Angular version 9之前,你可以选择加入编译器更新,这将使你的更新更加无缝。更新你的tsconfig.json文件如下:

{“compilerOptions”:{//为简洁起见省略“noimplicalany”:真正,“noImplicitReturns”:真正,“noImplicitThis”:真正,“nofallthroughcasesinswitch”:真正,“strictNullChecks”:真正//为简洁起见省略}}

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

  • noImplicitAny防止编译器暗示参数,变量或赋值的类型是类型的任何,这是默认情况下,编译器无法推断出类型或未明确声明类型的代码。
  • noImplicitReturns防止你在不被注意的情况下,也就是说,在你不知道的情况下,跌入一个函数能够返回任何隐式。这可以确保您正确地返回正确的类型,无论您所在的代码分支是否返回值。
  • noImplicitThis确保我们没有假设的价值。作为JavaScript开发人员,我们知道值取决于函数的执行上下文。这个编译器标志防止我们假设,或者允许编译器暗示上下文
  • nofallthroughcasesinswitch确保每一个案件声明是由一个适当的保护打破陈述防止案件落到了案件声明。
  • strictnullchecks.确保我们不允许两者未定义空值除非在TypeScript中显式声明,否则值不能全局可用或可赋值。这个标志是高度推荐它可以防止可能产生的错误无效合并和其他真假强制力。

渲染器弃用

人们期待已久的这种变化,所以这并不奇怪。弃用的渲染器最终从角度码布中删除。这意味着如果您的角度项目通过依赖注入依赖于弃用物渲染器类,您需要迁移到的对象Renderer2

值得庆幸的是,这种迁移是通过的ng更新命令我们要很快就会执行。所以,如果你是懒惰(像我一样),那么你现在可以跳过这个,让角update为您迁移它。

大多数方法都很容易更新渲染器Renderer2,但那些不会为您修复的人。

请确保在更新后检查git差异渲染器Renderer2迁移。

更新到最新的Angular 8补丁

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

NG更新@ Angular / Core @ 8 @ Angular / Cli @ 8

更新到角度版本9

我们做了!我们已准备好将您的角度项目通过Angular版本9通过ng更新:

ng更新@ 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.财产。默认值是念头美国,因此您需要根据源代码的区域设置为应用程序指定源语言环境:

{“$架构”:”。/ node_modules / @angular / cli / lib / config / schema.json”,“版本”:1,“newprojectroot”:“项目”,“项目”:{“angular-v9”:{“国际化”:{“sourceLocale”:“恩美”,“场所”:{“德”:{“翻译”:“src /地区/ messages.de.xlf”,“baseHref”:”“}}}}}}

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

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

  • 美国英语:/ en-US /
  • 多伊奇:/德/

因此,我修改了baseHref为了区域设置:

{“$架构”:”。/ node_modules / @angular / cli / lib / config / schema.json”,“版本”:1,“newprojectroot”:“项目”,“项目”:{“angular-v9”:{“国际化”:{“sourceLocale”:“恩美”,“场所”:{“德”:{“翻译”:“src /地区/ messages.de.xlf”,“baseHref”:“/ de /”}}}}}}

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

{“$架构”:”。/ node_modules / @angular / cli / lib / config / schema.json”,“版本”:1,“newprojectroot”:“项目”,“项目”:{“angular-v9”:{“架构师”:{“构建”:{“配置”:{“德”:{},“production-de”:{}}}}}}}

我移除了生产德配置。

最后,在项目中更新您的生产构建命令package.json文件包括新的- 光明标记来构建所有的本地化:

{“名称”:“angular-v9”,“版本”:“0.0.0”,“脚本”:{“ng”:“ng”,“服务:dist ":“HTTP-Server -P 8080 -C-1 Dist / Angular-V9”,“构建”:“ng build  -  prod --localize”,},

注意:

  • 首先,我有一个新的服务:dist.命令我使用HTTP-Server节点模块提供我的生产构建的本地化版本。
  • 其次,我更新了建立命令来包含new- 光明标记以构建所有本地化。

让我也提到您可以创建其他配置来构建特定语言环境或一组语言环境。

更新后的清单

成功升级到Angular version 9后,我们需要做两件小事:

  1. 从不推荐的迁移testbed.get()新方法testbed.inject ()方法。
  2. 删除不必要的entryComponents我们的财产@ngmodule()装饰器对象。

迁移到testbed.inject()

发布Angular版本9更新,我们的第一个任务是迁移testbed.get()testbed.inject ()

之前:

描述('filmservice',()=>{服务:filmservice.;beforeEach(()=>试验台configuretestingModule.({进口:(HttpClientTestingModule]}));('应该是创造的,()=>{服务=试验台得到(filmservice.);期望(服务)toBeTruthy();});});

后:

描述('filmservice',()=>{服务:filmservice.;beforeEach(()=>试验台configuretestingModule.({进口:(HttpClientTestingModule]}));('应该是创造的,()=>{服务=试验台注入<filmservice.>(filmservice.);期望(服务)toBeTruthy();});});

注意:

  • 我们改变testbed.get()testbed.inject ()
  • 函数返回的类型的泛型注入()方法。

删除entryComponents

使用Angular Version 9和新的常春藤渲染器,我们不需要明确地指示组件依赖图外部的组件的编译器。需要宣布的组件的一个很好的例子entryComponents数组是对话框。

此更新很简单,谁不喜欢删除代码。刚删除entryComponents数组的@ngmodule()应用程序中的装饰器。

之前:

@ngmodule.({宣言:(//为简洁起见省略PersonFilmsDialogComponent,personhomeplanetdialogcomponent.],entryComponents:(PersonFilmsDialogComponent,personhomeplanetdialogcomponent.]})出口PeopleModule{}

在我们删除了不必要之后entryComponents数组:

@ngmodule.({宣言:(//为简洁起见省略PersonFilmsDialogComponent,personhomeplanetdialogcomponent.]})出口PeopleModule{}

成功!

我们已成功更新为角度9和新的常春藤渲染引擎。

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

布莱恩F爱

嗨,我是布莱恩。我对类型名称,Angular和node.js感兴趣我嫁给了我最好的朋友邦妮,我住在波特兰和我滑雪(很多)。