AngularJS技术可行性替换研究

举报
Jet Ding 发表于 2020/09/30 16:21:09 2020/09/30
【摘要】 本文对AngularJS与Angular项目中的关键元素进行了对照说明, 希望对业务开发和升级有指导作用, 也希望对此话题感兴趣的朋友们有所裨益。

【引言】

最近收到一个调研需求,是关于AngularJS技术可行性替换研究。

本文我们就来具体探索一下这个话题。

今天的内容是关于如何一一对应的把AngularJS项目内容转化为Angular项目。

【概述】

Angular是当前和未来Angular技术的通用名称。

AngularJS是所有v1.x版本的Angular老技术的名称。

接下来我们会把AngularJS语法与对应的Angular语法做个比较,从而帮助大家顺利地把AngularJS项目过渡到Angular项目。

【模板基础】

模板是Angular应用中面向用户的部分,是用HTML编写的。下表列出了关键的AngularJSAngular模板语法的对应。

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  trueactuve类被应用到元素上。

可以指定多个类,如第二个例子所示。

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指令允许AngularJShref属性进行预处理,以便用适当的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指令允许AngularJSsrc属性进行预处理,以便用适当的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表达式值匹配的元素。

在这个例子中,如果没有设置favoriteHerongSwitch值为空,*ngSwitchDefault显示 "Please enter..."。如果设置了favoriteHero,那么app会通过调用一个组件方法检查。如果该方法返回true,则app选择*ngSwitchCase="true "并显示。"Excellent choice如果该方法返回false,应用程序会选择*ngSwitchCase="false "并显示:"No movie, sorry"

在这个例子中,ngSwitchCasengSwitchDefault之前的(*)是必须的。



【过滤器
/管道】

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中没有类似的管道。可以使用组件代码来排序。如果你需要在多个模板中使用相同的排序代码,可以考虑构建一个自定义管道或者工具类。

 

【模块/控制器/组件】

AngularJSAngular中,模块可以帮助把应用程序组织成内聚的功能块。

AngularJS中,编写的代码提供了控制器中的模型和视图的方法。在Angular中,你构建的是组件。

很多AngularJS代码都是用JavaScript编写的。Angular的代码是用TypeScript写的。

AngularJS

Angular

IIFE

(function () {

  ...

}());

AngularJS中,在控制器代码周围有一个立即调用的函数表达式(或IIFE),使其不在全局命名空间内。

 Angular 中,这不是问题,因为 ES 2015 模块会帮你处理命名空间。

模块

angular.module("movieHunter", ["ngRoute"]);

AngularJS中,一个Angular模块会跟踪控制器、服务和其他代码。第二个参数定义了这个模块所依赖的其他模块的列表。

NgModules

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

 

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

  }

Angular中,你可以将依赖关系作为参数传递给组件类构造函数。这个例子注入了一个MovieService。第一个参数的TypeScript类型告诉Angular要注入什么,即使是在minification之后也是如此。

 

【样式表】

样式表可以让你的应用程序有一个漂亮的外观。在AngularJS中,你可以为整个应用程序指定样式表。随着时间的增长,这可能会出现混乱的结果。

Angular中,你仍然可以为整个应用程序定义样式表,同时你也可以在特定的组件中封装一个样式表。

AngularJS

Angular

链接标签

<link href="styles.css" rel="stylesheet" />

AngularJSindex.html文件的头部使用链接标签来定义应用程序的样式。


     


     


     


     


     

样式配置

 

 "styles": [

              "styles.css"

            ],

通过Angular CLI,你可以在angular.json文件中配置你的全局样式。你可以将扩展名重命名为.scss来使用sass

 

StyleUrls

在Angular中,你可以使用@Component元数据的style或styleUrls属性来定义一个特定组件的样式表。

styleUrls: [ './movie-list.component.css' ],

这可以为单个组件设置适当的样式。

 

小结

本文对AngularJSAngular项目中的关键元素进行了对照说明, 希望对业务开发和升级有指导作用, 也希望对此话题感兴趣的朋友们有所裨益。

欢迎讨论。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。