AngularJS技术可行性替换研究
【引言】
最近收到一个调研需求,是关于AngularJS技术可行性替换研究。
本文我们就来具体探索一下这个话题。
今天的内容是关于如何一一对应的把AngularJS项目内容转化为Angular项目。
【概述】
Angular是当前和未来Angular技术的通用名称。
AngularJS是所有v1.x版本的Angular老技术的名称。
接下来我们会把AngularJS语法与对应的Angular语法做个比较,从而帮助大家顺利地把AngularJS项目过渡到Angular项目。
【模板基础】
模板是Angular应用中面向用户的部分,是用HTML编写的。下表列出了关键的AngularJS与Angular模板语法的对应。
AngularJS |
Angular |
捆绑/数据植入Your favorite hero is: {{vm.favoriteHero}} 在AngularJS中,大括号中的表达式表示单向绑定。将元素的值绑定到与此模板关联的控制器中的某个属性上。 绑定的前缀是controller别名(vm或$ctrl)。 |
捆绑/数据植入Your favorite hero is: {{favoriteHero}} 在Angular中,大括号中的模板表达式仍然表示单向绑定。把元素的值绑定到组件的某个属性上。绑定的上下文是隐含的。 |
过滤器 <td>{{movie.title | uppercase}}</td> AngularJS可以使用管道字符(|)来添加一个或多个过滤器。 例子中将标题属性转化为大写。 |
管道<td>{{movie.title | uppercase}}</td> 在Angular中,使用类似的语法用管道(|)字符来过滤输出,但现在称为管道。AngularJS中的许多(但不是全部)内置过滤器都是Angular中的内置管道。 |
本地变量<tr ng-repeat="movie in vm.movies"> <td>{{movie.title}}</td> </tr> 这里的movie是用户定义的本地变量。 |
输入变量<tr *ngFor="let movie of movies"> <td>{{movie.title}}</td> </tr> Angular有真正的模板输入变量,是使用let关键字显式定义的。. |
【模板指令】
AngularJS为模板提供了七十多个内置指令。
由于Angular的绑定系统能力更强,其中的许多指令在Angular中并不需要。以下是关键的AngularJS内置指令以及它们在Angular中的等价表示。
AngularJS |
Angular |
ng-app<body ng-app="movieHunter"> 应用程序的启动过程称为引导(bootstrapping)。 你可以在代码中引导一个AngularJS应用,但很多应用都是用ng-app指令声明性地引导,此时指定一个应用模块名称,如movieHunter。 |
引导main.ts
import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module'; import { environment } from './environments/environment';
if (environment.production) { enableProdMode(); }
platformBrowserDynamic().bootstrapModule(AppModule);
app.module.ts
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }
Angular没有bootstrap指令。要在代码中启动应用程序. 在main.ts中显式引导应用程序的根模块(AppModule). 在app.module.ts中显式引导应用程序的根组件(AppComponent)。 |
ng-class<div ng-class="{active: isActive}"> <div ng-class="{active: isActive, shazam: isImportant}" ></div> </div>
在AngularJS中,ng-class指令引入或者排除基于表达式的CSS类。表达式通常是一个键-值控制对象,对象的每个键定义为CSS类名,每个值定义为模板表达式,该表达式的每一个值都是一个模板表达式,该表达式的值会转化为一个布尔值。 在第一个例子中,如果 isActive 是 true,actuve类被应用到元素上。 可以指定多个类,如第二个例子所示。 |
ngClass<div [ngClass]="{'active': isActive}"> <div [ngClass]="{'active': isActive, 'shazam': isImportant}" > <div [class.active]="isActive"></div> </div> </div>
在Angular中,ngClass指令的工作原理类似。它根据一个表达式引入或者排除CSS类。 在第一个例子中,如果 isActive 是 true, active类被应用到元素中。 你可以指定多个类,如第二个例子所示。 Angular也有类的绑定,这也是添加或删除单个类的简便方法,如第三个例子所示。 |
ng-click<button ng-click="vm.toggleImage()"> <button ng-click="vm.toggleImage($event)">
在AngularJS中,ng-click指令在元素被点击时指定自定义行为。 在第一个例子中,当用户点击按钮时,vm控制器作为别名引用控制器中的toggleImage()方法被执行。 第二个例子演示了传递$event对象参数,向控制器提供关于事件的详细信息。 |
绑定到点击事件<button (click)="toggleImage()"> <button (click)="toggleImage($event)">
在Angular中,基于事件的AngularJS指令并不存在。相反,使用事件绑定定义从模板视图到组件的单向绑定。 对于事件绑定,在括号中定义目标事件的名称,并在等号的右边用引号指定一个模板语句。然后,Angular会为目标事件设置一个事件处理程序。当事件触发时,处理程序会执行模板语句。 在第一个例子中,当用户点击按钮时,组件中的toggleImage()方法被执行。 第二个例子演示了传递$event对象参数,向组件提供关于事件的详细信息。 |
ng-controller<div ng-controller="MovieListCtrl as vm"> 在AngularJS中,ng-controller指令将控制器附加到视图上。使用ng-controller(或将控制器定义为路由的一部分)将视图与与该视图相关联的控制器代码绑定。 |
元素装饰器@Component({ selector: 'app-movie-list', templateUrl: './movie-list.component.html', styleUrls: [ './movie-list.component.css' ], }) 在Angular中,模板不再指定它的关联控制器。相反,作为组件类装饰器的一部分,组件指定了它的关联模板。 |
ng-hide在AngularJS中,ng-hide指令基于表达式显示或隐藏相关的HTML元素 |
绑定到隐藏属性在Angular中,你使用的是属性绑定;没有内置的隐藏指令 |
ng-href<a ng-href="{{ angularDocsUrl }}">Angular Docs</a> ng-href指令允许AngularJS对href属性进行预处理,以便用适当的URL替换绑定表达式。 在AngularJS中,ng-href经常被用来激活路由作为导航的一部分。
<a ng-href="#{{ moviesHash }}">Movies</a> 在Angular中,路由的处理方式是不同的。 |
绑定到 href属性<a [href]="angularDocsUrl">Angular Docs</a> Angular使用的是属性绑定,没有内置的href指令。将元素的href属性放在方括号中,并将其设置为引用的模板表达式。 在Angular中,href不再用于路由。路由使用 routerLink,如下面的例子所示。 <a [routerLink]="['/movies']">Movies</a> |
ng-if<table ng-if="movies.length"> 在AngularJS中,ng-if指令会根据表达式删除或重新创建DOM的一部分元素。如果表达式为false,该元素将从DOM中移除。 在这个例子中,如果movies数组长度为0,<table>元素会从DOM中移除。 |
*ngIf<table *ngIf="movies.length"> Angular中的*ngIf指令与AngularJS中的ng-if指令的工作原理相同。它根据一个表达式来移除或重新创建DOM的一部分。 在这个例子中,如果movies数组长度为0,<table>元素会从DOM中移除。 例子中ngIf之前的(*)是必需的。 |
ng-model<input ng-model="vm.favoriteHero"/> 在AngularJS中,ng-model指令将表单控件绑定到与模板关联的控制器中的属性。这提供了双向绑定,即对视图中的值进行的任何更改都会与模型同步,而对模型的任何更改也会与视图中的值同步。 |
ngModel<input [(ngModel)]="favoriteHero" /> 在Angular中,双向绑定用[()]表示。这种语法是定义属性绑定(从组件到视图)和事件绑定(从视图到组件)的捷径,从而提供了双向绑定。 |
ng-repeat<tr ng-repeat="movie in vm.movies"></tr> 在AngularJS中,ng-repeat指令为指定的集合中的每一个项目重复渲染相关的DOM元素。 在这个例子中,表行(<tr>)元素为电影集合中的每一个电影对象重复渲染。 |
*ngFor<tr *ngFor="let movie of movies"> Angular中的*ngFor指令类似于AngularJS中的ng-repeat指令。它为指定的集合中的每一个项目重复渲染相关的DOM元素。更准确地说,它将定义的元素(在这个例子中是<tr>)和它的内容变成一个模板,并使用该模板为列表中的每个项实例化一个视图。 注意其他语法上的差异:ngFor之前的(*)是必需的;let关键字标识了movie作为输入变量;list介词是of,而不是in。 |
ng-show<h3 ng-show="vm.favoriteHero"> Your favorite hero is: {{vm.favoriteHero}} </h3>
在AngularJS中,ng-show指令会根据表达式显示或隐藏相关的DOM元素。 在这个例子中,如果favoriteHero变量是true,则会显示<h3>元素。 |
绑定到隐藏属性<h3 [hidden]="!favoriteHero"> Your favorite hero is: {{favoriteHero}} </h3>
Angular使用属性绑定;没有内置的show指令。对于隐藏和显示元素,绑定到HTML的隐藏属性。 要有条件地显示一个元素,将该元素的隐藏属性放在方括号中,并将其设置为一个与显示状态相反的模板表达式。 在这个例子中,如果favoriteHero变量不是true,<h3>元素就会被隐藏。 |
ng-src<img ng-src="{{movie.imageurl}}"> ng-src指令允许AngularJS对src属性进行预处理,以便用适当的URL替换绑定的表达式。 |
绑定到src属性<img [src]="movie.imageurl"> Angular使用属性绑定,没有内置的src指令。将 src 属性放在方括号中,并将其设置为引用的模板表达式。 |
ng-style<div ng-style="{color: colorPreference}"> 在AngularJS中,ng-style指令根据表达式在HTML元素上设置一个CSS样式。该表达式通常是一个键-值控制对象,对象的每个键定义为一个CSS属性,每个值定义为一个表达式,该表达式的值会被转化为适合样式的值。 在这个例子中,颜色样式被设置为colorPreference变量的当前值。 |
ngStyle<div [ngStyle]="{'color': colorPreference}"> <div [style.color]="colorPreference"> 在Angular中,ngStyle指令的工作原理类似。它根据一个表达式为HTML元素设置一个CSS样式。 在第一个例子中,颜色样式被设置为colorPreference变量的当前值。 第二个例子中显示Angular如何设定单一样式属性的另一方法。 |
ng-switch<div ng-switch="vm.favoriteHero && vm.checkMovieHero(vm.favoriteHero)" > <div ng-switch-when="true"> Excellent choice! </div> <div ng-switch-when="false"> No movie, sorry! </div> <div ng-switch-default> Please enter your favorite hero. </div> </div>
在AngularJS中,ng-switch指令会根据表达式的当前值选择其中一个模板来切换元素的内容。 在这个例子中,如果没有设置favoriteHero,模板会显示 " Please enter..."。如果设置了favoriteHero,它通过调用一个控制器方法来检查。如果该方法返回true,模板会显示 " Excellent choice!"。如果该方法返回false,模板会显示 " No movie, sorry!"。 |
ngSwitch<span [ngSwitch]="favoriteHero && checkMovieHero(favoriteHero)"> <p *ngSwitchCase="true"> Excellent choice! </p> <p *ngSwitchCase="false"> No movie, sorry! </p> <p *ngSwitchDefault> Please enter your favorite hero. </p> </span>
在Angular中,ngSwitch指令的工作原理类似。它显示一个*ngSwitchCase与当前ngSwitch表达式值匹配的元素。 在这个例子中,如果没有设置favoriteHero,ngSwitch值为空,*ngSwitchDefault显示 "Please enter..."。如果设置了favoriteHero,那么app会通过调用一个组件方法检查。如果该方法返回true,则app选择*ngSwitchCase="true "并显示。"Excellent choice!" 如果该方法返回false,应用程序会选择*ngSwitchCase="false "并显示:"No movie, sorry!"。 在这个例子中,ngSwitchCase和ngSwitchDefault之前的(*)是必须的。 |
【过滤器/管道】
Angular管道为模板中的数据提供格式化和内容转换,类似于AngularJS的过滤器。AngularJS中的许多内置过滤器在Angular中都有对应的管道。
AngularJS |
Angular |
currency<td>{{movie.price | currency}}</td> 格式化一个数字为货币显示输出。 |
currency<td>{{movie.price | currency:'USD':true}}</td> 两者类似。 |
date<td>{{movie.releaseDate | date}}</td> 根据要求的格式,将日期格式化为字符串。 |
date<td>{{movie.releaseDate | date}}</td> 两者类似。 |
filter<tr ng-repeat="movie in movieList | filter: {title:listFilter}"> 根据筛选标准,从定义的集合中选择一个子集。 |
none由于性能原因,Angular中没有类似的管道。在组件中进行过滤即可。如果需要在多个模板中使用相同的过滤代码,可以考虑构建一个自定义管道或者工具类。 |
json<pre>{{movie | json}}</pre> 将一个JavaScript对象转换为JSON字符串。 |
json<pre>{{movie | json}}</pre> 两者类似。 |
limitTo<tr ng-repeat="movie in movieList | limitTo:2:0"> 最多选择管道,第一个参数指定个数,第二个参数指定起始位置。 |
slice<tr *ngFor="let movie of movies | slice:0:2"> SlicePipe做了同样的事情,但参数的顺序是相反的,与JavaScript Slice方法保持一致。第一个参数是起始索引;第二个参数是个数。在组件内进行这类操作,可以提高性能。 |
lowercase<td>{{movie.title | lowercase}}</td> 将字符串转换为小写。 |
lowercase<td>{{movie.title | lowercase}}</td> 两者类似。 |
number<td>{{movie.starRating | number}}</td> 将一个数字格式化为文本。 |
number<td>{{movie.starRating | number}}</td> <td>{{movie.starRating | number:'1.1-2'}}</td> <td>{{movie.approvalRating | percent: '1.0-2'}}</td>
Angular数字管道是类似的。 它在定义小数时提供了更多的功能,如上图第二例所示。 Angular还有一个百分比管道,它将一个数字格式化为局部百分比,如第三个例子所示。 |
orderBy<tr ng-repeat="movie in movieList | orderBy : 'title'"> 按照表达式指定的顺序显示集合。在这个例子中, movieList以电影标题排序。 |
none由于性能原因,Angular中没有类似的管道。可以使用组件代码来排序。如果你需要在多个模板中使用相同的排序代码,可以考虑构建一个自定义管道或者工具类。 |
【模块/控制器/组件】
在AngularJS和Angular中,模块可以帮助把应用程序组织成内聚的功能块。
在AngularJS中,编写的代码提供了控制器中的模型和视图的方法。在Angular中,你构建的是组件。
很多AngularJS代码都是用JavaScript编写的。Angular的代码是用TypeScript写的。
AngularJS |
Angular |
IIFE(function () { ... }()); 在AngularJS中,在控制器代码周围有一个立即调用的函数表达式(或IIFE),使其不在全局命名空间内。 |
无在 Angular 中,这不是问题,因为 ES 2015 模块会帮你处理命名空间。 |
模块angular.module("movieHunter", ["ngRoute"]); 在AngularJS中,一个Angular模块会跟踪控制器、服务和其他代码。第二个参数定义了这个模块所依赖的其他模块的列表。 |
NgModulesimport { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }
用NgModule装饰器定义的NgModule也有同样的作用。 import:指定这个模块所依赖的其他模块列表。 声明:跟踪你的组件、管道和指令。 |
控制器注册angular .module("movieHunter") .controller("MovieListCtrl", ["movieService", MovieListCtrl]); AngularJS在每个控制器中都有代码,可以查找一个合适的Angular模块,并将控制器与该模块注册关联。 第一个参数是控制器的名称。第二个参数定义了注入到这个控制器中的所有依赖项的字符串名,以及控制器函数的引用。 |
组件装饰@Component({ selector: 'app-movie-list', templateUrl: './movie-list.component.html', styleUrls: [ './movie-list.component.css' ], })
Angular在组件类中添加了一个装饰符来提供任何所需的元数据。@Component装饰器声明该类是一个组件,并提供了关于该组件的元数据,例如它的选择器(或标签)和模板。 这是你如何在Angular中将模板与逻辑关联的方法,而逻辑是在组件类中定义的。 |
控制器函数
function MovieListCtrl(movieService) { }
在AngularJS中,在控制器函数中编写模型和方法的代码。 |
组件类
export class MovieListComponent { }
在Angular中,你创建一个组件类来包含数据模型和函数方法。使用 TypeScript 导出关键字来导出类,以便将函数导入到 NgModules 中。 |
依赖注入
MovieListCtrl.$inject = ['MovieService']; function MovieListCtrl(movieService) { }
在AngularJS中,你可以将任何依赖关系作为控制器函数的参数传递进来。这个例子注入了一个MovieService。 为了防止minification问题,需要明确告诉Angular应该在第一个参数中注入一个MovieService的实例。 |
依赖注入constructor(movieService: MovieService) { } 在Angular中,你可以将依赖关系作为参数传递给组件类构造函数。这个例子注入了一个MovieService。第一个参数的TypeScript类型告诉Angular要注入什么,即使是在minification之后也是如此。 |
【样式表】
样式表可以让你的应用程序有一个漂亮的外观。在AngularJS中,你可以为整个应用程序指定样式表。随着时间的增长,这可能会出现混乱的结果。
在Angular中,你仍然可以为整个应用程序定义样式表,同时你也可以在特定的组件中封装一个样式表。
AngularJS |
Angular |
链接标签<link href="styles.css" rel="stylesheet" /> AngularJS在index.html文件的头部使用链接标签来定义应用程序的样式。
|
样式配置"styles": [ "styles.css" ], 通过Angular CLI,你可以在angular.json文件中配置你的全局样式。你可以将扩展名重命名为.scss来使用sass。 StyleUrls在Angular中,你可以使用@Component元数据的style或styleUrls属性来定义一个特定组件的样式表。 styleUrls: [ './movie-list.component.css' ], 这可以为单个组件设置适当的样式。 |
【小结】
本文对AngularJS与Angular项目中的关键元素进行了对照说明, 希望对业务开发和升级有指导作用, 也希望对此话题感兴趣的朋友们有所裨益。
欢迎讨论。
- 点赞
- 收藏
- 关注作者
评论(0)