Home >Web Front-end >JS Tutorial >How to upgrade AngularJS to Angular2+? Example introduction to angularjs upgrade

How to upgrade AngularJS to Angular2+? Example introduction to angularjs upgrade

寻∝梦
寻∝梦Original
2018-09-08 15:53:532042browse

This article mainly introduces the upgrade of angularjs, from angularjs to angularjs2, now let us look at this article together

Summarize a few months We worked overtime to upgrade two projects. One project uses UpgradeModule and the other uses DowngradeModule. Make a record as follows: (ng1->AngularJS; ng2 ->Angular2). For details, please see the official documentation: https: //angular.io/guide/upgrade

The advantages, disadvantages and usage methods of typescript that need to be used will not be described here.

1. UpgradeModule: This is the earliest parallel upgrade method released by Angular. The disadvantage is that the performance is relatively poor, and it is relatively simple to understand. Just create an Angular2 app first, and then add the ng1 controller Wrap them directly in /service/directive and let them run directly in the ng2 environment.

Step by step:

* Start from ng2 app:

** Delete ng-app from index.html;

** Add main. ts:

import { NgModule } from '@angular/core';
import { UpgradeModule } from '@angular/upgrade/static';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 
import { AppModule } from './app/app.module';
 
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
    const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
    upgrade.bootstrap(document.body, ['carepilot'], { strictDi: true });
});

** Add app.module.ts: All modules are defined here

import { NgModule, forwardRef } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';
 
@NgModule({
    imports: [
        BrowserModule,
        UpgradeModule
    ],
    bootstrap: []
})
 
export class AppModule {
    ngDoBootstrap() {}
}

** Add tsconfig.json: Define how to compile ts->js

{
    "compileOnSave": false,
    "compilerOptions": {
        "sourceMap": true,
        "declaration": false,
        "moduleResolution": "node",
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "noImplicitAny": true,
        "target": "es5",
        "typeRoots": [
            "node_modules/@types"
        ],
        "lib": [
            "es2015",
            "dom"
        ]
    },
    "exclude": [
        "node_modules"
    ]
}

** systemjs.config.js: Use systemjs to load dependent modules. During parallel conversion, the general example is to use systemJS to load modules;

/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
    System.config({
        paths: {
            'npm:': 'node_modules/'
        },
        map: {
            app: 'app',
            '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
            '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
            '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
            '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
            '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
            '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
            '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
            '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
            '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
            'rxjs': 'npm:rxjs'
        },
        packages: {
            app: {
                defaultExtension: 'js'
            },
            rxjs: {
                defaultExtension: 'js',
                format: 'cjs'
            }
        }
    });
})(this);

** Change index. html: Need to load some libraries required by ng2 (note: the following zone.js, etc., need to be copied to your running directory using tools such as gulp)

<script></script>
<script></script>
<script></script>
<script></script>

<!-- inject:js -->
<!-- endinject -->

<script>
System.import(&#39;main.js&#39;)
.then(null, console.error.bind(console));
</script>

Now, this hybrid The app should be able to run. The next task is to upgrade the controllers one by one and step on the pitfalls one by one;

To put it simply, when upgrading, controller->component, directive -> component/directive , service -> service, pipe/filter -> pipe;

* Example: Upgrade a controller to component (if you want to see more, go to the PHP Chinese websiteAngularJS Development Manual中学)

import {
    Component,
    Inject
} from '@angular/core';
import { Broadcaster } from '../../services/broadcaster';
 
@Component({
    selector: 'about',
    templateUrl: './about.component.html'
})
export class AboutComponent {
 
    constructor(private broadcaster: Broadcaster) {
    }
 
    print(): void {
        this.broadcaster.broadcast('printContents', 'printable');
    }
}

* Because most of the program is still ng1 code, in order to allow ng1 and ng2 things to communicate, you need to downgrade the ng2 module first:

angular.module('interestApp')

.directive('pinControls',

upgradeAdapter.downgradeNg2Component(PinControlsComponent));

Update config Routing in .js (assuming ui-state is used):

.state('add', {

template: "<add-pin></add-pin>",

url: '/add'

* The same problem, some controllers need to rely on some previous services after they are upgraded. At this time, it is necessary to temporarily upgrade the service of ng1 to ng2 to For use by ng2 components. During the upgrade process, I only encountered the need to do this for ui-route. At this time, types are needed. You can find the definition of the corresponding library here http://definitelytyped.org/docs/angular-ui- -angular-ui-router/modules/ng.html

* After the upgrade, the most awkward things are $scope and $rootscope. In ng1, the global rootscope is very comfortable to use, but it is canceled in ng2. Now, you need to define a service yourself to replace the previous rootscope. The current component cannot directly use the scope with =, > to bind the value. You need to use @input and @output to pass the value in and out, which corresponds to the previous =,> Value passing process;

* Use ng2 Router to define routes: Of course, you can also continue to use the upgraded version of ui-route @ui-route;

const AppRouting: Routes = [
    { path: 'app', component: DashboardComponent, canLoad: [AuthGuard], canActivate: [AuthGuard], data: { pageTitle: 'Dashboard' }];

* After painful Struggle (the use of new methods, changes in habits, it turns out that some ng1 libraries are not maintained and no one has upgraded to ng2, find alternatives or write your own How to upgrade AngularJS to Angular2+? Example introduction to angularjs upgrade), finally upgraded all the ng1 things, it is time The legacy and support programs of ng1 have been deleted and turned into a complete ng2 program.

** Delete upgrademodule:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
 
platformBrowserDynamic().bootstrapModule(AppModule);

** Delete all upgrade modules and downgrade modules;

** Add an appcomponent to load the initial route: (Here it is assumed that you use the default route of ng2. If you continue to use ui-route, continue to use ui-view)

import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
 
@Component({
  selector: 'app-root',
    template: `
    <p>
    <router-outlet></router-outlet>
    </p>
  `
})
export class AppComponent {
  constructor(private route: Router) {
        let loc = window.location.pathname.toString();
        if (loc == '/login' || loc == '/') {
            this.route.navigate(['login']);
        }
    }
}

* It succeeded immediately, and finally used angular-cli to manage the compilation process And module loading, this thing is a good thing (although there are some unsatisfactory aspects, such as release does not support JIT, etc. How to upgrade AngularJS to Angular2+? Example introduction to angularjs upgrade)


  • Now you only need npm (some people use yarn), and bower can be laid off.

  • Systemjs can also take a call;

  • Gulp or grunt needs specific analysis at this time. If the server is more complicated, it is recommended to keep it to start the server. Using concurrent, you can use angular-cli to manage the client code and gulp/grunt to manage the service when npm run dev. End;

Now, all the upgrades are completed. Of course, the actual process will definitely encounter various dissatisfaction. Let’s deal with the specific situation. This method can be used if the project is small. Comparatively It's easy to understand, there are many examples online, and it can be upgraded quickly. If the project is relatively large and takes several months to upgrade, then the following downgrade method should be used.

2. Downgrade: The official introduction is as precious as gold, which is difficult to understand for people who are trying this thing for the first time.

原理:downgrade是不改变原来的ng1程序,新建一个ng2+程序,然后把这个程序做成一个模块,直接注入到ng1里头,这样会避免一些额外的change事件,从而避免了不必要的消息循环,这样来提升性能。

用下面的5步升级到ng2+:

第一步:写一个新的ng2+程序,然后注入到ng1里头:

main.ts: (XXXXXX替换成你的ng1的app的名字就行了)

import { NgModule, forwardRef, StaticProvider } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { downgradeModule, downgradeComponent, setAngularLib } from '@angular/upgrade/static';
 
declare const angular: any;
declare const window: any;
const bootstrapFn = (extraProviders: StaticProvider[]) => {
    const platformRef = platformBrowserDynamic(extraProviders);
    return platformRef.bootstrapModule(AppModule);
};
 
const downgradedModule = downgradeModule(bootstrapFn);
 
angular.module('XXXXXX.ng2', [
    downgradedModule
]);
angular.module('XXXXXX.ng2').directive('template', downgradeComponent({ component: template}));

* app.js (就这里麻烦,试了一天才试出来,这么注入,然后加载)

(function() {
    angular.module('XXXXXXX', [
        // all the old modules
        'XXXXXXX.ng2'
    ]);
    // eslint-disable-next-line
    if (window.ignoreNg2ForTest) {
        // temporary not load ng2 module in karma test
        fetchData().then(bootstrapApplication);
    } else {
        // normal hybrid entrance
        loadMain().then(fetchData).then(bootstrapApplication);
    }
 
 
    function loadMain() {
        return System.import('main');   // load main.ts
    }
 
    function fetchData() {
        // old logic
    }
 
    function bootstrapApplication() {
        angular.element(document).ready(function() {
            angular.bootstrap(document, ['XXXXXXXX'], { strictDi: true }); // bootstrap app with ng1
        });
    }
 
}());

* 同样,在index.html里加入一些依赖(升级完都可以删)

<script></script>
<script></script>
<script></script>
<script></script>

* 手动拷一些依赖到dest 文件夹:(我们用的gulp)

pipes.builtAngularVendorScriptsDev = function() {
    return gulp.src([
        './node_modules/core-js/client/shim.min.js',
        ............
    ], {base: './node_modules'})
        .pipe(gulp.dest('dist.dev/node_modules'));
};

* JSPM: 不用这东西的话release 里头的客户端有近百M,会疯的,虽然这个东西也bug重重,临时用用还是可以的。用它以后release的客户端代码只有十几M,可以接受了。

gulp.task('build-jspm-prod', ['hybrid-tsbuild'], function() {
    return jspm({
            config: './client/systemjs.config.js',
            bundleOptions: {
                minify: true,
                mangle: false
            },
            bundleSfx: true,
            bundles: [
                { src: paths.tsOutput + '/*', dst: 'main.js' }
            ]
        }).pipe(gulp.dest('dist.prod'));
});


第二步:升级一个个的controller/service/pipe/directive等等,这个过程相当痛苦,原来代码的耦合,莫名其妙的event emit和不知道在哪儿的event handler。全局的rootscope遍地都是,牵一发动全身。自己解耦吧,没什么好办法。


第三步:升级路由,这个虽然没有上一步那么煎熬,也很头疼,很多地方都要改,

* 如果用route的话参见上面upgrademodule里的例子就好了;

* 如果使用@ui-route的话,state现在需要这么定义:(abstract我还没有研究出来有什么用)

export const registerState = {
    parent: 'app',
    name: 'register',
    url: '/register/{activationCode}',
    component: RegisterComponent,
    data: { pageTitle: 'Register' }
};

第四步:删除ng1的东西;

第五步:使用angular-cli管理依赖:

* 参照上面upgrademodule对应的步骤就好;

* 这时候可以删除JSPM了,这东西和SystemJS都是定时炸弹,bug重重啊,目前angular-cli比较稳定;


到这里,应该你的程序已经升级到了ng2+,目前是ng5,建议升级过程中把anglar相应的版本写死,这东西更新太快,你随着它升随时出现已有的包不兼容,很头疼,我们暂时定格在5.0。

我是升级完了站着说话不腰疼,上面的东西只能帮有需要的朋友节约一点点时间,最大的时间消耗在升级controller和解耦的过程中。那里如果有什么问题可以在下面留言,能帮上的话尽量帮大家省省时间。How to upgrade AngularJS to Angular2+? Example introduction to angularjs upgrade



备注一:替换规则。


  • ng-bind-html       [innerHTML]

  • ng-model             [(ngModel)]                                        // 这个和ng1的双向绑定基本一个意思

  • ng-class                [ngClass]

  • ng-disabled          [disabled]

  • ng-click                 (click)

  • ng-if                     *ngIf

  • ng-repeat           *ngFor                                              // E.g. *ngFor="let task of currentChecklist.open; let i = index;"

  • ng-show               *ngIf

  • ng-src                   [src]

  • ng-hide                 *ngIf

  • ng-submit            (ngSubmit)

  • ng-style                [ngStyle]

备注二:可能遇到的问题

  • JS:

    • 消息处理:ng2+里没有了scope继承,所以自己定义全局的消息处理是必要的;

  • HTML模板:

    • Directive conflict: It is best to separate the defined names. If it is called

This article ends here (if you want to see more, go to the PHP Chinese website AngularJS User Manual to learn). If you have any questions, you can ask them below Leave a message with a question.

The above is the detailed content of How to upgrade AngularJS to Angular2+? Example introduction to angularjs upgrade. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn