如何使用ngUpgrade从AngularJS升级到Angular

Angular (2+) is here, and we’re all super excited about it. For some of us, though, we’re still maintaining large AngularJS (1.x) codebases at work. How do we start migrating our application to the new version of Angular – especially if we can’t afford to take six months away from a feature development for a complete rewrite?

Angular(2+)在这里,我们都对此感到非常兴奋。 但是,对于我们中的某些人,我们仍在维护大型AngularJS(1.x)代码库。 我们如何开始将应用程序迁移到新版本的Angular中-尤其是如果我们不能花6个月的时间进行功能重写以进行完全重写时?

That’s where the ngUpgrade library comes in. ngUpgrade is the official tool to allow you to migrate your application litle by little. It lets Angular run side-by-side along with your AngularJS code for as long as you need to slowly upgrade.

这就是ngUpgrade库的来源。ngUpgrade是允许您少量迁移应用程序文档的官方工具。 只要您需要缓慢升级,它就可以使Angular与AngularJS代码并排运行。

In this guide, you will install and set up ngUpgrade and Angular. Then, you’ll learn the basics of rewriting components.

在本指南中,您将安装并设置ngUpgrade和Angular。 然后,您将学习重写组件的基础知识。

(P.S. If the length of this guide freaks you out, don’t worry. I’ve built a step-by-step, super detailed video program called Upgrading AngularJS that covers all of this in detail.)

(PS:如果本指南的篇幅太吓人了,请放心。我已经构建了一个名为Upgradeing AngularJS的分步,超详细的视频程序,其中详细介绍了所有这些。)

我们的出发点 (Our Starting Point)

To get started with ngUpgrade, your application needs to meet a few prerequisites:

要开始使用ngUpgrade,您的应用程序需要满足一些先决条件:

  1. Code organized by feature (not by type) and every file contains only one item (like a directive or service)

    代码按功能(不是按类型)组织,并且每个文件仅包含一项(如指令或服务)
  2. TypeScript set up

    TypeScript设置
  3. Using a module bundler (most people use Webpack)

    使用模块捆绑器(大多数人使用Webpack)
  4. Using AngularJS 1.5+ with controllers replaced by components

    将AngularJS 1.5+与控制器替换为组件一起使用

(If you’re lost on any of that, we cover it all in parts 1 and 2 of the course.)

(如果您迷失了其中的任何一个,我们将在本课程的第 1部分和第2部分中介绍所有内容。)

For now, though, take a minute to clone or fork the course sample project on GitHub (don’t forget to run npm install). Checkout this commit to see our starting point:

不过,现在就花点时间在GitHub上克隆或创建该课程示例项目 (不要忘记运行npm install )。 查看此提交以查看我们的起点:

git checkout fdfcf0bc3b812fa01063fbe98e18f3c2f4bcc5b4

git checkout fdfcf0bc3b812fa01063fbe98e18f3c2f4bcc5b4

We’ve got an Order System project that we can use to work through ngUpgrade. Starting at this commit, our application meets all of the above criteria. We’re using component architecture, TypeScript, and Webpack (we’ve even got builds for both development and production).

我们有一个Order System项目,可用于完成ngUpgrade。 从此提交开始,我们的应用程序满足所有以上条件。 我们正在使用组件体系结构,TypeScript和Webpack(我们甚至为开发和生产提供了构建)。

Note: In many large AngularJS apps, you just can’t move everything into a brand new Git repository and wipe out years of history. You also might be using a different app structure than the CLI. If you can use the CLI for your upgrade, then feel free to do so. This guide, however, will teach you the manual setup here so that you can have complete control over your upgrade.

注意 :在许多大型AngularJS应用中,您只是无法将所有内容移至全新的Git存储库中并抹去多年的历史。 您可能还使用了与CLI不同的应用程序结构。 如果您可以使用CLI进行升级,请随时进行升级。 但是,本指南将在此处教您手动设置,以便您可以完全控制升级。

安装Angular和ngUpgrade (Installing Angular & ngUpgrade)

We’re ready to install Angular, ngUpgrade, and all of the peer dependencies. In the sample project, go ahead and update your package.json dependencies array so it looks like this:

我们准备安装Angular,ngUpgrade和所有对等依赖项。 在示例项目中,继续并更新package.json依赖项数组,如下所示:

"dependencies": {
    "@angular/common": "^5.2.5",
    "@angular/compiler": "^5.2.5",
    "@angular/core": "^5.2.5",
    "@angular/forms": "^5.2.5",
    "@angular/platform-browser": "^5.2.5",
    "@angular/platform-browser-dynamic": "^5.2.5",
    "@angular/router": "^5.2.5",
    "@angular/upgrade": "^5.2.5",
    "angular": "1.6.6",
    "angular-route": "1.6.6",
    "bootstrap": "3.3.7",
    "core-js": "^2.5.3",
    "jquery": "^2.2.4",
    "lodash": "4.17.4",
    "moment": "~2.17.1",
    "reflect-metadata": "^0.1.12",
    "rxjs": "^5.5.6",
    "zone.js": "^0.8.20"
}

(We’re going to use Angular 5 in this series, even though the sample project uses version 4. Don’t sweat it - the steps are identical.)

(即使样例项目使用版本4,我们仍将在本系列中使用Angular5。不要费力-步骤相同。)

We could put all of these packages in one long command in the terminal with the save flag, but we will take the time to explain what each of these packages are.

我们可以使用save标志将所有这些软件包放在终端中的一个长命令中,但是我们将花一些时间来解释这些软件包中的每一个。

First are our libraries under the @angular namespace:

首先是我们在@angular命名空间下的库:

  • @angular/common: These are the commonly needed services, pipes, and directives for Angular. This package also contains the new HttpClient as of version 4.3, so we no longer need @angular/http.

    @angular/common :这些是Angular常用的服务,管道和指令。 这个软件包还包含4.3版以后的新HttpClient ,因此我们不再需要@angular/http

  • @angular/compiler: This is Angular’s template compiler. It takes the templates and converts them into the code that makes your application run and render. You almost never need to interact with it.

    @angular/compiler :这是Angular的模板编译器。 它采用模板并将其转换为使您的应用程序运行和呈现的代码。 您几乎不需要与之互动。

  • @angular/core: These are the critical runtime parts of Angular needed by every application. This has things like the metadata decorators (e.g. Component, Injectable), all the dependency injection, and the component life-cycle hooks like OnInit.

    @angular/core :这些是每个应用程序所需的Angular关键运行时部分。 它具有诸如元数据装饰器(例如ComponentInjectable ),所有依赖项注入以及诸如OnInit类的组件生命周期挂钩的功能。

  • @angular/forms: This is just everything we need with forms, whether template or reactive.

    @angular/forms :这就是表单所需的一切,无论是模板还是React式。

  • @angular/platform-browser: This is everything dom and browser related, especially pieces that help render the dom. This is the package that includes bootstrapStatic, which is the method that we use for bootstrapping our applications for production builds.

    @angular/platform-browser :这是dom和浏览器相关的所有内容,尤其是有助于渲染dom的片段。 这是一个包含bootstrapStatic的软件包,这是我们用于引导应用程序进行生产构建的方法。

  • @angular/platform-browser-dynamic: This package includes providers and another bootstrap method for applications that compile templates on the client. This is the package that we use for bootstrapping during development and we’ll cover switching between the two in another video.

    @angular/platform-browser-dynamic :该软件包包括提供程序和用于在客户端上编译模板的应用程序的另一种引导方法。 这是我们在开发过程中用于引导的软件包,我们将在另一个视频中介绍两者之间的切换。

  • @angular/router: As you might guess, this is just the router for Angular.

    @angular/router :您可能会猜到,这只是Angular的路由器。

  • @angular/upgrade: This is the ngUpgrade library, which allows us to migrate our AngularJS application to Angular.

    @angular/upgrade :这是ngUpgrade库,它使我们可以将AngularJS应用程序迁移到Angular。

After all of our Angular packages come our polyfill packages that are dependencies of Angular:

在所有的Angular软件包发布之后,我们的polyfill软件包即为Angular的依赖项:

  • core-js patches the global context or the window with certain features of ES6 or ES2015.

    core-js使用ES6或ES2015的某些功能修补全局上下文或窗口。

  • reflect-metadata is a polyfill library for the annotations that Angular uses in its classes.

    reflect-metadata是一个用于Angular在其类中使用的注释的polyfill库。

  • rxjs: This is the library that includes all of the observables that we’ll use for handling our data.

    rxjs :这是一个库,其中包含我们将用于处理数据的所有可观察对象。

  • zone.js is a polyfill for the Zone specification, which is part of how Angular manages change detection.

    zone.js是用于Zone规范的zone.js ,这是Angular管理变更检测的一部分。

Sometimes, there are conflicts involving the version of TypeScript you’re using. This can be due to RxJS, the Angular compiler, or Webpack. If you start getting weird compilation errors, do some research to find out of any of those need a specific version range of TypeScript for the version you’re using.

有时,涉及您正在使用的TypeScript版本的冲突。 这可能是由于RxJS,Angular编译器或Webpack引起的。 如果开始出现怪异的编译错误,请进行一些研究以找出那些需要使用特定TypeType特定版本范围的TypeScript。

Open your terminal, cd into the public folder of the project, and run npm install (you’re welcome to install and use Yarn if you’d prefer). You will see that all of your packages were installed.

打开你的终端, cdpublic项目的文件夹,然后运行npm install (欢迎您安装和使用的纱线如果你愿意)。 您会看到所有软件包都已安装。

We’re now ready to make our application a hybrid application by dual-booting both AngularJS and Angular.

现在,我们准备通过双重引导AngularJS和Angular使我们的应用程序成为混合应用程序。

设置ngUpgrade (Setting Up ngUpgrade)

To set up ngUpgrade, we need to do a series of steps to allow AngularJS and Angular to run alongside of each other.

要设置ngUpgrade,我们需要执行一系列步骤以允许AngularJS和Angular彼此并存。

步骤1:从index.html移除Bootstrap (Step 1: Removing Bootstrap from index.html)

The first thing we need to do is remove our bootstrap directive from index.html. This is how AngularJS normally gets started up at page load, but we’re going to bootstrap it through Angular using ngUpgrade. So, just open index.html and remove that data-ng-app tag. (if you’re using strict DI in your own app, you’ll remove ng-strict-di as well in this step.) Your index.html file will look like this now:

我们需要做的第一件事是从index.html删除我们的bootstrap指令。 这就是AngularJS通常在页面加载时启动的方式,但是我们将使用ngUpgrade在Angular中引导它。 因此,只需打开index.html并删除该data-ng-app标签。 (如果您在自己的应用程序中使用严格的DI,则在此步骤中也将删除ng-strict-di 。)您的index.html文件现在看起来像这样:


  
    Amazing, Inc. Order System
  
  
      
      

第2步:更改AngularJS模块 (Step 2: Changing the AngularJS Module)

Now we need to make some changes in AngularJS module. Open up app.ts. The first thing we need to do is rename app.ts to app.module.ajs.ts to reflect that it’s the module for AngularJS. It’s kind of a lengthy name, but in Angular we want to have our type in our file name. Here we’re using app.module and then we’re adding that ajs to specify that it’s for AngularJS instead of our root app.module for Angular (which we’ll make in a second).

现在我们需要在AngularJS模块中进行一些更改。 打开app.ts。 我们需要做的第一件事是将app.ts重命名为app.module.ajs.ts以反映它是AngularJS的模块。 这是一个冗长的名称,但是在Angular中,我们希望在文件名中输入类型。 在这里,我们使用app.module ,然后添加该ajs以指定它用于AngularJS,而不是我们的根app.module用于Angular(我们将在稍后进行介绍)。

As the app is now, we’re just using AngularJS, so we have all of our import statements here and we’re registering everything on our Angular module. However, now what we’re going to do is export this module and import it into our new Angular module to get it up and running. So, on line 28 let’s create a string constant of our app name:

就像现在的应用程序一样,我们仅使用AngularJS,因此我们在这里拥有所有的import语句,并且正在Angular模块上注册所有内容。 但是,现在我们要做的是导出此模块,并将其导入到新的Angular模块中,以使其启动并运行。 因此,在第28行,我们创建一个应用程序名称的字符串常量:

const MODULE_NAME = 'app';

const MODULE_NAME = 'app';

Then we’ll replace our app string with module name in our Angular.module declaration:

然后,在Angular.module声明中将应用程序字符串替换为模块名称:

angular.module(MODULE_NAME, ['ngRoute'])
// component and service registrations continue here

And finally, we need to export our constant:

最后,我们需要导出常量:

export default MODULE_NAME;

export default MODULE_NAME;

You can check out the finished AngularJS module at this stage here.

您可以在此阶段检查出来的成品AngularJS模块这里 。

步骤3:建立Angular应用程式模组 (Step 3: Creating the Angular App Module)

Our AngularJS module is ready to go, so we’re now ready to make our Angular module. We’ll then import our AngularJS module so we can manually bootstrap it here. That’s what let’s the two frameworks run together, and enables ngUpgrade to bridge the gap between them.

我们的AngularJS模块已准备就绪,因此现在可以开始制作Angular模块了。 然后,我们将导入AngularJS模块,以便在此处手动引导它。 这就是两个框架一起运行的目的,并使ngUpgrade能够弥合它们之间的差距。

The first thing we need to do is create a new file at the same level as our AngularJS module called app.module.ts. Now for the first time, you’re about to see a pattern that’s going to become familiar to you throughout your upgrade: making and exporting a class, decorating it with an annotation, and importing all of the dependencies.

我们需要做的第一件事是在与名为app.module.ts的AngularJS模块相同的级别上创建一个新文件。 现在,第一次,您将看到一个在整个升级过程中将变得熟悉的模式:制作和导出类,用注释装饰它以及导入所有依赖项。

In our new app module, let’s create a class named AppModule:

在我们的新应用程序模块中,让我们创建一个名为AppModule的类:

export class AppModule { 
}

Now let’s add our first annotation (also called a decorator). An annotation is just a bit of metadata that Angular uses when building our application. Above our new class, we’ll use the NgModule annotation and pass in an options object:

现在,让我们添加第一个注释 (也称为decorator )。 注释只是Angular在构建应用程序时使用的一些元数据。 在新类之上,我们将使用NgModule批注并传递一个options对象:

@NgModule({})
export class AppModule { 
}

If you’re following along in an editor like Visual Studio Code, you’ll see that TypeScript is mad at us because it doesn’t know what NgModule is. This is because we need to import it from the Angular core library. Above our decorator, we can fix this with:

如果在Visual Studio Code之类的编辑器中进行操作,您会发现TypeScript对我们很生气,因为它不知道NgModule是什么。 这是因为我们需要从Angular核心库中导入它。 在我们的装饰器上方,我们可以通过以下方法解决此问题:

import { NgModule } from '@angular/core';

import { NgModule } from '@angular/core';

Now, in our options object for ngModule, we need to pass an array of imports. The imports array specifies other NgModules that this NgModule will depend on. (These imports are different than the TypeScript imports at the top of our file.) Right now, we need the BrowserModule and the UpgradeModule:

现在,在ngModule的options对象中,我们需要传递一个导入数组。 imports数组指定此NgModule依赖的其他NgModule。 (这些导入与文件顶部的TypeScript导入不同。)现在,我们需要BrowserModule和UpgradeModule:

import { NgModule } from '@angular/core';

@NgModule({
    imports: [
        BrowserModule,
        UpgradeModule
    ]
})
export class AppModule { }

Of course, we don’t have those imported either at the top of our file, so we need to do that too. After our first import, we can add:

当然,文件的顶部也没有导入这些文件,因此我们也需要这样做。 首次导入后,我们可以添加:

import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static';

import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static';

There’s an UpgradeModule in both upgrade and upgrade/static. We want to use the static one because it provides better error reporting and works with AOT (ahead-of-time) compiling.

upgradeupgrade/static中都有一个UpgradeModule。 我们要使用静态代码,因为它提供了更好的错误报告,并且可以与AOT(提前)编译一起使用。

We’ve got the basic scaffolding of our root module for Angular set up and we’re ready to do the bootstrapping itself.

我们已经安装了用于Angular的根模块的基本脚手架,并且已经准备好进行引导。

步骤4:在Angular模块中引导 (Step 4: Bootstrapping in the Angular Module)

To bootstrap our application, the first thing we need to do is inject UpgradeModule using a constructor function:

要引导我们的应用程序,我们需要做的第一件事是使用构造函数注入UpgradeModule:

constructor(private upgrade: UpgradeModule){
}

We don’t need to do anything in our constructor function. The next thing we’ll do is override the doBootstrap function. After the constructor, type:

我们不需要在构造函数中做任何事情。 我们要做的下一件事是覆盖doBootstrap函数。 在构造函数之后,键入:

ngDoBootstrap(){
}

Next, we’ll use the UpgradeModule’s bootstrap function. It has the same signature as the Angular bootstrap function, but it does a couple extra things for us. First, it makes sure that Angular and AngularJS run in the correct zones, and then it sets up an extra module that allows AngularJS to be visible in Angular and Angular to be visible in AngularJS. Lastly, it adapts the testability APIs, so that Protractor will work with hybrid apps, which is super important.

接下来,我们将使用UpgradeModule的引导功能。 它具有与Angular Bootstrap函数相同的签名,但是它为我们做了一些额外的事情。 首先,确保Angular和AngularJS在正确的区域中运行,然后设置一个额外的模块,该模块允许AngularJS在Angular中可见,而Angular在AngularJS中可见。 最后,它适应了可测试性API,因此Protractor可以与混合应用程序一起使用,这非常重要。

Let’s add it:

让我们添加它:

ngDoBootstrap(){
        this.upgrade.bootstrap(document.documentElement, [moduleName], {strictDi: true});
}

We’re first passing in our document element and then our AngularJS module inside an array. Lastly, just so you can see an example of this, we’re adding a config object so we can switch on strict dependency injection.

我们首先要传递document元素,然后是数组中的AngularJS模块。 最后,为了让您看到一个示例,我们添加了一个config对象,以便可以启用严格的依赖注入。

You may be wondering where the moduleName came from. We need to import it up with our other import statements:

您可能想知道moduleName来源。 我们需要将其与其他导入语句一起导入:

import moduleName from './app.module.ajs';

import moduleName from './app.module.ajs';

Here’s what our completed app.module.ts file looks like now:

这是我们现在完成的app.module.ts文件的外观:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';
import moduleName from './app.module.ajs';

@NgModule({
    imports: [
        BrowserModule,
        UpgradeModule
    ]
})
export class AppModule {
    constructor(private upgrade: UpgradeModule) { }

    ngDoBootstrap(){
        this.upgrade.bootstrap(document.documentElement, [moduleName], {strictDi: true});
    }
}

This is going to be a pattern that’s going to become familiar to you over time.

随着时间的流逝,这将会成为一种模式。

步骤5:创建main.ts (Step 5: Creating main.ts)

Now that we’ve got our AngularJS module and our Angular module set up, we need an entry point that’s going to bring these two together and get our application running. Let’s create a new file under our src folder called main.ts.

现在我们已经设置了AngularJS模块和Angular模块,我们需要一个入口点来将这两个部分放在一起并使应用程序运行。 让我们在src文件夹下创建一个名为main.ts的新文件。

In main.ts, we need to import a few things, tell Angular which version of AngularJS to load, and then tell it to bootstrap our Angular module. First, we need to import two polyfill libraries and Angular’s platformBrowserDynamic function:

main.ts ,我们需要导入一些东西,告诉Angular加载哪个版本的AngularJS,然后告诉它引导我们的Angular模块。 首先,我们需要导入两个polyfill库和Angular的platformBrowserDynamic函数:

import 'zone.js';
import 'reflect-metadata';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

Why platformBrowserDynamic instead of just platformBrowser? Angular has two ways to compile: a dynamic option and a static option. In the dynamic option (known as just-in-time, or JIT), the Angular compiler compiles the application in the browser and then launches the app. The static option (known as ahead-of-time, or AOT) produces a much smaller application that launches faster. This is because the Angular compiler runs ahead of time as part of the build process. We’re just going to be using the JIT method here along with the Webpack dev server.

为什么选择platformBrowserDynamic而不是platformBrowser ? Angular有两种编译方式:动态选项和静态选项。 在动态选项(称为即时或JIT)中,Angular编译器在浏览器中编译应用程序,然后启动该应用程序。 静态选项(称为“提前”或“ AOT”)生成的应用程序小得多,启动速度更快。 这是因为Angular编译器会在构建过程中提前运行。 我们将在这里与Webpack开发服务器一起使用JIT方法。

(In the course we spend an entire module setting up AOT compiling for production.)

(在此过程中,我们花费了整个模块来设置用于生产的AOT编译。)

Now we need to import both our Angular and AngularJS modules, as well as a method that tells Angular which version of AngularJS to use:

现在,我们需要导入我们的Angular和AngularJS模块,以及一种告诉Angular使用哪个版本的AngularJS的方法:

import { setAngularLib } from '@angular/upgrade/static';
import * as angular from 'angular';

import { AppModule } from './app.module';

Now to finish this off, we just need to call setAngularLib and pass in our version of AngularJS, and we need to call platformBrowserDynamic and tell it to bootstrap our app module. The finished file looks like this:

现在完成此操作,我们只需要调用setAngularLib并传入我们的AngularJS版本,就需要调用platformBrowserDynamic并告诉它引导我们的应用程序模块。 完成的文件如下所示:

import 'zone.js';
import 'reflect-metadata';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { setAngularLib } from '@angular/upgrade/static';
import * as angular from 'angular';
import { AppModule } from './app.module';

setAngularLib(angular);
platformBrowserDynamic().bootstrapModule(AppModule);

Now that we’ve got that set up, we just need to change our Webpack entry point in our config.

现在我们已经完成了设置,我们只需要在配置中更改Webpack入口点即可。

步骤6:更新Webpack (Step 6: Updating Webpack)

Hopefully, this process of bootstrapping a hybrid application is starting to make sense to you. We have a main.ts file that’s our entry point, which sets up our AngularJS library and bootstraps our Angular module. Then, our Angular module bootstraps our AngularJS module. That’s what let’s both frameworks run alongside each other.

希望,这种引导混合应用程序的过程开始对您有意义。 我们有一个main.ts文件作为我们的入口点,该文件设置了我们的AngularJS库并引导了我们的Angular模块。 然后,我们的Angular模块引导我们的AngularJS模块。 这就是我们两个框架相互并行运行的原因。

We’re now ready to change our Webpack config so that it’s starting with our main.ts file and not one of our app module files. Open up webpack.common.js (it’s under the webpack-configs folder). Under module.exports for entry, we’ll change our app root to main.ts:

现在,我们准备更改Webpack的配置,使其从main.ts文件而不是我们的应用模块文件之一开始。 打开webpack.common.js (位于webpack-configs文件夹下)。 在module.exports entry ,我们将应用程序根目录更改为main.ts

entry: {
        app: './src/main.ts',
}

测试应用程序 (Testing the Application)

Now, we’re ready to see our hybrid application in action. You can run the dev server by opening a terminal and running these commands:

现在,我们准备好看看我们的混合应用程序了。 您可以通过打开终端并运行以下命令来运行开发服务器:

cd server
npm start
cd ../public
npm run dev

You will see that Webpack is loading and that our TypeScript is compiled successfully.

您将看到Webpack正在加载,并且我们的TypeScript已成功编译。

Let’s go check out the browser at localhost:9000. You can see that our application still runs on our dev server.

让我们在localhost:9000处签出浏览器。 您可以看到我们的应用程序仍在我们的开发服务器上运行。

You might see a couple of warnings in the console about core-js depending on your version, but don’t worry about them, they won’t affect us. You can also open the network tab and see the vendor bundle and app bundle:

您可能会在控制台中看到一些关于core-js的警告,具体取决于您的版本,但请不要担心,它们不会影响我们。 您还可以打开“网络”标签,查看供应商捆绑包和应用捆绑包:

The vendor bundle is absolutely huge, and that’s because 1) we’re running Webpack dev server, which means it’s not minifying anything, 2) we’re running Angular in dynamic compiling, so it’s shipping the compiler code to the browser as well. We’ll fix this downstream when we talk about AOT compiling, but we can navigate around here and see that all of our data is still loading.

供应商捆绑包绝对是巨大的,这是因为1)我们正在运行Webpack开发服务器,这意味着它没有缩小任何内容,2)我们在动态编译中运行Angular,因此也将编译器代码也运送到了浏览器。 在谈论AOT编译时,我们将在下游修复此问题,但我们可以在此处浏览并看到所有数据仍在加载中。

We now have Angular and AngularJS running alongside of each other, which means we’ve successfully set up our hybrid application. That means we’re ready to start upgrading our application piece by piece.

现在,我们使Angular和AngularJS彼此并行运行,这意味着我们已经成功设置了混合应用程序。 这意味着我们已经准备好开始逐步升级应用程序。

重写和降级您的第一个组件 (Rewriting & Downgrading Your First Component)

步骤1:重写组件 (Step 1: Rewriting the Component)

We’ve got our application bootstrapped and running in hybrid mode, so we’re ready to get started with migrating each piece of our application. One common approach is to pick a route and then start from the bottom up to rewrite each piece, starting with whatever has the least dependencies. This allows us to iteratively upgrade our application so that every point along the way, we have something that’s deployable to production.

我们已经启动了应用程序并在混合模式下运行,因此我们准备开始迁移应用程序的每一部分。 一种常见的方法是选择一条路线,然后从下至上重新编写每个部分,从具有最小依赖性的内容开始。 这使我们可以迭代地升级应用程序,以便在开发过程中的每一个环节上,我们都可以部署一些产品。

Let’s start with the home route because that’s an easy one with just the home component. We’ll first rename our home component to home.component.ts.

让我们从本地路由开始,因为只有本地组件才是简单的路由。 我们将首先将home组件重命名为home.component.ts

Now we need to rewrite our home component as an Angular class. The first thing we need to do is import component from the Angular core library at the top of our file:

现在我们需要将home组件重写为Angular类。 我们需要做的第一件事是从文件顶部的Angular核心库中导入组件:

import { Component } from '@angular/core'

import { Component } from '@angular/core'

The next thing we’ll do is convert our function homeComponentController to a class. We can also capitalize it and remove the controller at the end of the name, so that it’s just called HomeComponent. Lastly, let’s get rid of the parenthesis. It looks like this now:

我们要做的下一件事是将函数homeComponentController转换为一个类。 我们还可以将其大写并删除名称末尾的controller ,以便将其称为HomeComponent 。 最后,让我们摆脱括号。 现在看起来像这样:

class HomeComponent {
    var vm = this;
    vm.title = 'Awesome, Inc. Internal Ordering System';
}

Now let’s clean up what’s inside the class. We no longer need the declaration of vm since we’re using a class. We can also add a property of title as a string, and move setting the title to a constructor function. Our class looks like this now:

现在,让我们清理一下类中的内容。 由于我们使用的是类,因此不再需要vm的声明。 我们还可以将title属性添加为字符串,并将标题设置为构造函数。 我们的班级现在看起来像这样:

class HomeComponent {
    title: string;
    constructor(){
        title = 'Awesome, Inc. Internal Ordering System';
    }
}

We also need to export this class and then delete that export default line.

我们还需要export此类,然后删除该export default行。

Now we need to apply the Component metadata decorator that we imported to tell Angular that this is a component. We can replace the home component object with the component decorator and an options object:

现在我们需要应用导入的Component元数据装饰器,以告诉Angular这是一个组件。 我们可以用组件装饰器和选项对象替换home组件对象:

@Component({
}

The first option of our component decorator is the selector. This is just the HTML tag that we’ll use to reference this component, which will just be ‘home’. Note that in Angular, the selector is a string literal. This is different than in AngularJS, where we would name the component in camel case, and then it would translate to an HTML tag with hyphens. Here, we’re going to put exactly the tag that we want to use. In this case, we’re just keeping it to 'home’, so it doesn’t matter too much. After that, we’ll specify our template, just like we did with AngularJS, so I’ll just say template: template. And believe it or not, that’s all there is to it. Our finished component looks like this:

我们的组件装饰器的第一个选择是selector 。 这只是我们将用来引用此组件HTML标记,它将只是“ home”。 请注意,在Angular中,选择器是字符串文字。 这与AngularJS不同,在AngularJS中,我们以驼峰形式命名该组件,然后将其转换为带有连字符HTML标记。 在这里,我们将准确放置我们要使用的标签。 在这种情况下,我们只是将其保留在“家”中,所以没有太大关系。 之后,我们将指定template ,就像我们对AngularJS所做的那样,所以我只说template: template 。 信不信由你,这就是全部。 我们完成的组件如下所示:

import { Component } from '@angular/core';

const template = require('./home.html');

@Component({
    selector: 'home',
    template: template
})
export class HomeComponent {
    title: string;
    constructor(){
        this.title = 'Awesome, Inc. Internal Ordering System';
    }
}

Note: If you’re working on an application that will use the AOT compiler, you’ll want to use templateUrl instead of what we’re doing here and make some changes to Webpack. This is totally fine for JIT and the development server, though.

注意 :如果您正在使用AOT编译器的应用程序上工作,则需要使用templateUrl而不是我们在此处所做的事情,并对Webpack进行一些更改。 不过,对于JIT和开发服务器来说,这完全没问题。

步骤2:降级AngularJS的组件 (Step 2: Downgrading the Component for AngularJS)

We now need to use the ngUpgrade library to “downgrade” this component. “Downgrading” means to make an Angular component or service available to AngularJS. “Upgrading,” on the other hand, means to make an AngularJS component or service available to Angular. We’ll cover that in another article. Luckily, downgrading is super easy.

现在,我们需要使用ngUpgrade库来“降级”该组件。 “降级”是指使Angular组件或服务可用于AngularJS。 另一方面,“升级”意味着使Angular可以使用AngularJS组件或服务。 我们将在另一篇文章中介绍。 幸运的是,降级非常容易。

First, we need to do two things at the top of our file along with our imports. We need to import the downgradeComponent function from the Angular upgrade library declare a variable called angular so we can register this component on our AngularJS module. This looks like this:

首先,我们需要在文件顶部和导入文件之间做两件事。 我们需要从Angular升级库中导入downgradeComponent函数,声明一个名为angular的变量,以便可以在AngularJS模块上注册此组件。 看起来像这样:

import { downgradeComponent } from '@angular/upgrade/static'; declare var angular: angular.IAngularStatic;

import { downgradeComponent } from '@angular/upgrade/static'; declare var angular: angular.IAngularStatic;

Downgrading the component is fairly straightforward. Down at the bottom of our component, we’ll register this component as a directive. We’ll pass in our directive name, which is just home, the same as our selector in this case. Then after that, we’ll pass in the downgradeComponent function from ngUpgrade. This function converts our Angular component into an AngularJS directive. Finally, we’ll cast this object as angular.IDirectiveFactory. The finished registration looks like this:

降级组件非常简单。 在组件的底部,我们将把该组件注册为指令。 在这种情况下,我们将传入指令名称,即home ,与选择器相同。 然后,我们将从ngUpgrade传入downgradeComponent函数。 该函数将我们的Angular组件转换为AngularJS指令。 最后,我们将该对象转换为angular.IDirectiveFactory 。 完成的注册如下所示:

app.module('app')
  .directive('home', downgradeComponent({component: HomeComponent} as angular.IDirectiveFactory);

Now we have a downgraded Angular component that’s available to our AngularJS application. You might be wondering why we registered that directive here at the bottom of this file instead of importing and registering it in our AngularJS module TypeScript file. The end goal is to get rid of that file altogether once all of our application is converted, so we want to gradually remove things from that file and then eventually delete it altogether when we uninstall AngularJS. This works great for sample applications or rapid migrations (more on that in a second).

现在,我们有一个降级的Angular组件,可用于我们的AngularJS应用程序。 您可能想知道为什么我们在此文件的底部此处注册了该指令,而不是将其导入并注册到我们的AngularJS模块TypeScript文件中。 最终目标是在转换完所有应用程序后完全删除该文件,因此我们希望逐步从该文件中删除内容,然后最终在卸载AngularJS时将其完全删除。 这对于示例应用程序或快速迁移非常有用(稍后介绍更多)。

Go ahead and open up app.module.ajs.ts and remove the import of homeComponent on line 12 and the component registration on line 37.

继续前进,打开app.module.ajs.ts并取出的进口homeComponent上线12和上线37的组件注册。

AOT编译快速说明 (A Quick Note on AOT Compiling)

This method of downgrading – registering the downgraded component in the component file and removing it from the AngularJS module file – works perfectly well for development or if you plan on quickly rewriting your application before you deploy. However, the Angular AOT compiler for production won’t work with this method. Instead, it wants all of our downgraded registrations in the AngularJS module.

这种降级方法(将降级的组件注册到组件文件中并将其从AngularJS模块文件中删除)对于开发或计划在部署之前快速重写应用程序非常适用。 但是,用于生产的Angular AOT编译器不适用于此方法。 相反,它希望在AngularJS模块中所有降级的注册。

The downgrade is identical, but instead you’d:

降级是相同的,但是您可以:

  1. Import downgradeComponent in app.module.ajs.ts (you’ve already got angular in there so you don’t need to declare it).

    app.module.ajs.ts导入downgradeComponent (您已经在其中找到了angular ,因此无需声明它)。

  2. Change the import of homeComponent to import { HomeComponent } from './home/home.component'; since we switched to a named export.

    将homeComponent的导入更改为import { HomeComponent } from './home/home.component'; 因为我们切换到命名出口。

  3. Change the component registration to the exact same directive registration shown above.

    将组件注册更改为与上面显示的完全相同的指令注册。

You can read more about setting up ngUpgrade for AOT in this article, as well as in Course 3 of Upgrading AngularJS (there’s a whole module that lays it out step-by-step).

您可以在本文中以及在AngularJS升级课程3(有一个完整的模块逐步介绍)中了解有关为AOT设置ngUpgrade的更多信息。

步骤3:更新范本 (Step 3: Updating the Template)

After a component is updated, we need to be sure to update its template so it complies with the new Angular syntax. In this case, there are only minimal changes you must make to homeComponent. We just need to remove $ctrl on line two. The template looks like this now:

组件更新后,我们需要确保更新其模板,使其符合新的Angular语法。 在这种情况下,只需对homeComponent进行最少的更改。 我们只需要删除第二行的$ctrl 。 现在,模板如下所示:

{{title}}

Now we have a fully functional downgraded home component in our hybrid application.

现在,我们的混合应用程序中具有功能齐全的降级家庭组件。

步骤4:添加到Angular应用模块 (Step 4: Add to the Angular App Module)

Let’s add our new Angular component to our Angular module. Open up app.module.ts. First, we need to just import our home component after all of our other imports:

让我们将新的Angular组件添加到Angular模块中。 打开app.module.ts 。 首先,我们需要在所有其他导入之后仅导入home组件:

import { HomeComponent } from './home/home.component';

import { HomeComponent } from './home/home.component';

Now, we need to add HomeComponent to our Angular application. All Angular components must be added to a declarations array of our NgModule. So, after line 12 in our options object, we’ll add a new array called declarations and add our component:

现在,我们需要将HomeComponent添加到Angular应用程序中。 必须将所有Angular组件添加到我们的NgModule的declarations数组中。 因此,在options对象的第12行之后,我们将添加一个称为声明的新数组并添加我们的组件:

declarations: [
        HomeComponent
]

We also need to create an entryComponents array and add our HomeComponent to that. All downgraded components must be added to this entryComponents array. We’ll add it after our declarations:

我们还需要创建一个entryComponents数组,并向其中添加entryComponents 。 必须将所有降级的组件添加到此entryComponents数组。 我们将在declarations后添加它:

entryComponents: [
        HomeComponent
]

With that, we’re finished.

至此,我们完成了。

测试它是否有效 (Testing That it Works)

Let’s run those same commands as before and make sure our application is still working. Here are those commands again:

让我们运行与以前相同的命令,并确保我们的应用程序仍在运行。 这又是这些命令:

cd server
npm start
cd ../public
npm run dev

Head back over to localhost:9000. You can see that our home component is loading in the browser as a rewritten Angular component! You can even go look at the Sources tab of Chrome devtools just to be positive. Open up webpack://, scroll down to ./src/home/home.component.ts, and sure enough, there it is!

回到localhost:9000 。 您会看到我们的home组件作为重写的Angular组件正在浏览器中加载! 您甚至可以直接看一下Chrome devtools的“来源”标签。 打开webpack:// ,向下滚动到./src/home/home.component.ts ,可以肯定的是!

结论 (Conclusion)

Here’s what you’ve accomplished in this guide:

这是本指南中您完成的工作:

  • Installed Angular and ngUpgrade

    已安装Angular和ngUpgrade
  • Set up an Angular module

    设置一个Angular模块
  • Bootstrapped Angular and AngularJS

    自举Angular和AngularJS
  • Updated Webpack

    更新了Webpack
  • Rewritten and downgraded your first component

    重写并降级您的第一个组件

In a followup to this guide, we’ll talk about the basics of rewriting and downgraded services.

在本指南的后续文章中,我们将讨论重写和降级服务的基础知识。

翻译自: https://www.digitalocean.com/community/tutorials/how-to-upgrade-from-angularjs-to-angular-with-ngupgrade

你可能感兴趣的:(vue,python,java,编程语言,javascript,ViewUI)