0

0

AngularJS如何升级到Angular2+?angularjs升级的实例介绍

寻∝梦

寻∝梦

发布时间:2018-09-08 15:53:53

|

2156人浏览过

|

来源于php中文网

原创

本篇文章主要的介绍了关于angularjs的升级,从angularjs升级到angularjs2+,现在就让我们一起来看这篇文章吧

总结一下几个月时间加班赶工升级的两个项目,一个项目使用的是upgrademodule,另一个使用的是downgrademodule,如下做个记录:(ng1->angularjs; ng2+->angular2+),具体的可以看官方文档:https://angular.io/guide/upgrade

需要用到的typescript的优缺点和使用方法就不在这里赘述了。

一、 UpgradeModule:这个是Angular最早放出来的并行升级方式,缺点是性能方面比较差,理解起来还比较简单,就是先创建一个Angular2+的app,然后把ng1的controller/service/directive之类的直接包裹一下,让他们在ng2+的环境下直接跑。

Step by step:

* 从ng2 app 启动:

** 从index.html删除ng-app;

** 加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 });
});

** 加app.module.ts: 所有的模块都在这里定义

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() {}
}

** 加tsconfig.json:定义怎么编译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: 用systemjs加载依赖的模块,在并行转换的时候一般的例子都是使用systemJS来加载模块;

/**
 * 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);

** 改index.html:需要加载一些ng2需要的库(注意:下面的几个zone.js等等,需要自己使用gulp之类的工具拷贝到你的运行目录中)

<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>

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

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

现在,这个hybrid的app应该可以跑起来了,下面的工作就是把controller一个一个升级,一个个踩坑的过程;

简单来说,升级的时候controller->component, directive -> component/directive, service -> service, pipe/filter -> pipe;

* 例子:升级一个controller到component(想看更多就到PHP中文网AngularJS开发手册中学习)

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');
    }
}

* 因为程序里大部分还是ng1的代码,为了能让ng1和ng2+的东西能沟通,需要把ng2+的模块先downgrade:

angular.module('interestApp')

.directive('pinControls',

upgradeAdapter.downgradeNg2Component(PinControlsComponent));

更新config.js里的路由(假设使用ui-state):

.state('add', {

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

url: '/add'

* 同样的问题,一些controller升级了以后需要依赖一些以前的service,这时候需要暂时将ng1的service升级到ng2+,以供ng2+的component使用,我在升级过程中只遇到ui-route需要这么做,这时候需要用types,可以到这里找对应的库的定义http://definitelytyped.org/docs/angular-ui--angular-ui-router/modules/ng.html

* 升级后,最别扭的就是$scope和$rootscope,在ng1里头,全局的rootscope用的爽的不得了,在ng2+里头取消了,需要自己定义一个service来替代以前的rootscope,现在的component不能直接使用scope用= , >这样来绑定值了,要用@input和@output把值传入和传出来,对应于以前的=,>传值过程;

* 使用ng2+的Router定义路由:当然也可以继续使用ui-route的升级版@ui-route;

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

* 经过痛苦的斗争(新方法的使用,习惯的改变,原来一些ng1的库没人维护也没人升级到ng2+,找替代品或者自己写一个大哭),终于把ng1的东西都升级完了,这时候该删除ng1的遗留和支持程序了,变成一个完全的ng2+程序了。

** 删除upgrademodule:

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

** 删除全部的upgrade 模块、downgrade模块;

** 加一个appcomponent用来加载初始的路由:(这里假设你用ng2+默认的route, 如果继续使用ui-route,继续使用ui-view即可)

import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
 
@Component({
  selector: 'app-root',
    template: `
    <p class="main-page">
    <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']);
        }
    }
}

* 马上就成功了,最后使用angular-cli来管理编译过程和模块加载,这东西是个好玩意(虽然也有一些不如人意的地方,比如release不支持JIT等等的问题敲打

  • 现在只需要npm就好了(有人用yarn),bower可以下岗了.

  • Systemjs也就可以谢幕了;

  • Gulp 或者grunt这时候需要具体情况具体分析,如果服务端比较复杂,建议还是保留,用来启动服务端,使用concurrent就可以在npm run dev时候angular-cli管客户端代码,gulp/grunt管服务端;

现在,全部的升级就完成了,当然实际过程肯定会遇到种种不如意,具体情况具体对待吧,这种方式如果项目小的话可以采用,比较好理解,网上的例子也多,很快升级完。如果项目比较大,需要几个月时间升级的话,那就要使用下面的downgrade的方式了。

二、downgrade:官方的介绍惜墨如金,给第一次弄这玩意的人挺难理解的。

原理: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 (就这里麻烦,试了一天才试出来,这么注入,然后加载)

Spirit Me
Spirit Me

SpiritMe允许用户使用数字化身制作视频,这些化身可以模拟用户的声音和情感

下载
(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 src="node_modules/systemjs/dist/system.js"></script>
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></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和解耦的过程中。那里如果有什么问题可以在下面留言,能帮上的话尽量帮大家省省时间。微笑

备注一:替换规则。

  • 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冲突:定义的名字最好分开,ng1里叫<my-input的话,ng2+里最好叫<ng-my-input,不然冲突.

本篇文章到这就结束了(想看更多就到PHP中文网AngularJS使用手册中学习),有问题的可以在下方留言提问。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

76

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

117

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

350

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

63

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

109

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

108

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

243

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

684

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

179

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
第二期_大前端线上班
第二期_大前端线上班

共345课时 | 56万人学习

TypeScript深入讲解—贪吃蛇实战
TypeScript深入讲解—贪吃蛇实战

共30课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号