【第1208期】AngularJS 1.x平滑升級Angular實戰

2021-02-28 前端早讀課

前言

不知道還有多少人的項目還在用Angular,這篇升級實戰可以看看,今日早讀文章由@Perry翻譯投稿分享。

正文從這開始~

當我們從AngularJS 1.x升級到Angular(2/4/5)時,我們通常會先準備AngularJS 1.x的代碼:

這個過程會引入像組件這類新的AngularJS 1.x技術。並且,引入TypeScript和像SystemJS或者Webpack之類的模塊加載器是準備已有代碼的進一步工作。這樣做的目的是為了讓代碼更接近Angular便於更好的集成。

但是,在一些情況下,準備已有的代碼成本很大。例如,試想一下這樣的情形,當你不想修修改已有的AngularJS1.x的代碼,並且想要寫一些Angular的應用。當這樣的情況在你的項目中發生,跳過準備階段是一個好的主意。

這篇文章一步步展示如何完成這個過程。像官方的升級教程一樣,包含準備代碼的工作,這裡也是升級流行的AngularJS 1.x 手機分類實例。

即使這個實例覆蓋了AngularJS 1.5中引入的組件,這裡展示的對使用控制器(controller)和指令(directive)的代碼也適用。

整個實例代碼可以在Github 倉庫中找到。為了接下來每一步更容易,我針對每一步做了一個代碼提交。

第一步:創建新的Angular應用

一開始,本文假設我們使用Angular CLI來搭建一個新的Angular應用:

ng new migrated

為了讓這個新的方案結構清晰,在src目錄下創建了一個文件夾給已有的AngularJS代碼,另一個文件夾給新的Angular代碼。
在下面的實例中,我使用了ng1和ng2來命名:

創建完之後,移動除了tsconfig.app.json, tsconfig.spec.json, favicon.ico和index.html之外的文件到ng2文件夾中。

通過.angular-cli.json文件來通知CLI的編譯任務有關修改的新代碼結構。在這個文件中使用assets欄位,我們也可以告訴CLI直接拷貝ng1文件夾到輸出的目錄中。

{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"project": {
   "name": "migrated"
 },
"apps": [
           {
           "root": "src",
           "outDir": "dist",
           "assets": [
                   "ng1",
                   "assets",
                   "favicon.ico"
           ],
           "index": "index.html",
           "main": "ng2/main.ts",
           "polyfills": "ng2/polyfills.ts",
           "test": "ng2/test.ts",
           "tsconfig": "tsconfig.app.json",
           "testTsconfig": "tsconfig.spec.json",
           "prefix": "app",
           "styles": [
                   "ng2/styles.css"
           ],
           "scripts": [],
           "environmentSource": "ng2/environments/environment.ts",
           "environments": {
                       "dev": "ng2/environments/environment.ts",
                       "prod": "ng2/environments/environment.prod.ts"
           }
       }
   ],
"e2e": {
   "protractor": {
       "config": "./protractor.conf.js"
   }
 },
"lint": [
   {
       "project": "tsconfig.app.json"
   },
   {
       "project": "tsconfig.spec.json"
   },
   {
       "project": "tsconfig.e2e.json"
   }
 ],
"test": {
   "karma": {
       "config": "./karma.conf.js"
   }
 },
"defaults": {
   "styleExt": "css",
   "component": {}
 }
}

現在拷貝了整個AngularJS 1.x應用到ng1文件夾中,但是忽略index.html。為了舊的應用可以在修改過的文件結構下工作,我們要做一些調整。這包括修改模板文件的引用還有JSON文件和圖片文件。

之後,我們可以合併舊的index.html到文件夾src下新的文件中。

<!doctype html>
<htmllang="en">
<head>
   <metacharset="utf-8">
   <title>Migrated</title>
   <basehref="/">
   <!-- ng1 -->
   <link rel="stylesheet"href="ng1/bower_components/bootstrap/dist/css/bootstrap.css" />
   <link rel="stylesheet"href="ng1/app.css" />
   <link rel="stylesheet"href="ng1/app.animations.css" />
   <script src="ng1/bower_components/jquery/dist/jquery.js"></script>
   <script src="ng1/bower_components/angular/angular.js"></script>
   <script src="ng1/bower_components/angular-animate/angular-animate.js"></script>
   <script src="ng1/bower_components/angular-resource/angular-resource.js"></script>
   <script src="ng1/bower_components/angular-route/angular-route.js"></script>
   <script src="ng1/app.module.js"></script>
   <script src="ng1/app.config.js"></script>
   <script src="ng1/app.animations.js"></script>
   <script src="ng1/core/core.module.js"></script>
   <script src="ng1/core/checkmark/checkmark.filter.js"></script>
   <script src="ng1/core/phone/phone.module.js"></script>
   <script src="ng1/core/phone/phone.service.js"></script>
   <script src="ng1/phone-list/phone-list.module.js"></script>
   <script src="ng1/phone-list/phone-list.component.js"></script>
   <script src="ng1/phone-detail/phone-detail.module.js"></script>
   <script src="ng1/phone-detail/phone-detail.component.js"></script>
<!-- /ng1 -->
   <meta name="viewport"content="width=device-width, initial-scale=1">
   <link rel="icon"type="image/x-icon"href="favicon.ico">
</head>
<body ng-app="phonecatApp">
<!-- ng1 -->
<div class="view-container">
<div ng-viewclass="view-frame"></div>
</div>
<!-- /ng1 -->
<app-root></app-root>
</body>
</html>

注意這個合併後的index.html包含了AngularJS 1.x應用所需要的CSS文件和腳本。還通過ng-app啟動AngularJS 1.x應用,並通過包含有ng-view指令的div提供出來的殼。這個是路由激活對應配置模板的地方。

在這個文件中,我們也可以找到Angular應用的根元素。針對Angular生成打包文件的引用是不需要的,因為他們由編譯任務自動生成。

當這個應用啟動(ng serve),它將會將兩個應用獨立的加載到瀏覽器中。可以通過訪問http://localhost:4200來查看。

由於兩個應用是獨立啟動的,因此他們無法互相通信和交換使用服務和組件。為了使這些工作,我們需要讓他們作為混合應用啟動。下一章節會介紹如何做到。

第二步:啟動一個AngularJS+Angular的混合應用

為了同時啟動AngularJS 1.x和Angular應用,我們可以利用Angular的ngUpgrade模塊:

npm install @angular/upgrade --save

由於我們不想啟動Angular(2/4/5等)應用,我們將indexl.html文件中的根組件移除:

<!-- remove root component -->
<!--
 <app-root></app-root>-->

現在,我們可以一起同時啟動兩個應用。為此,引入UpgradeModule模塊到Angular應用的AppModule中。從bootstrap中移除AppComponent,從而手動啟動混合應用:

import { BrowserModule } from'@angular/platform-browser';
import { NgModule } from'@angular/core';
import { UpgradeModule, downgradeComponent } from'@angular/upgrade/static';
import { AppComponent } from'./app.component';
import { Ng2DemoComponent } from"ng2/app/ng2-demo.component";
@NgModule({
 declarations: [
   AppComponent
 ],
 imports: [
   BrowserModule,
   UpgradeModule
 ],
 providers: [],
// bootstrap: [AppComponent] // No Bootstrap-Component
})
export class AppModule {
constructor(private upgrade: UpgradeModule) { }
 ngDoBootstrap() {
   this.upgrade.bootstrap(document.body, ['phonecatApp'], { strictDi: true });
 }
}

就像你所看到的,這個例子通過使用注入的UpgradeModule模塊在ngDoBootstrap中啟動混合應用。為了阻止啟動AngularJS 1.x應用兩次,我們需要在index.html文件中移除ng-app指令。

當我們開始應用,我們可以看到AngularJS 1.x的組件:

儘管如此,這個一個包含兩個版本Angular的混合應用。為了證明這一點,下一章節將會顯示如何在展示的AngularJS組件中使用Angular組件。

第三步:降級一個Angular組件

為了展示如何在混合應用的AngularJS中使用Angular組件,教程中會使用一個非常簡單的組件:

// src/app/ng2-demo.component.ts
import { Component, OnInit } from'@angular/core';
@Component({
 selector: 'ng2-demo',
 template: `
   <h3>Angular 2 Demo Component</h3>    <img width="150" src="..." />  `
})
export class Ng2DemoComponent  {
}

原始碼中顯示的圖片可以在腳手架中AppComponent找到。

為了在AngularJS模板中使用這個組件,我們需要降級它。ngUpgrade提供了一個函數downgradeComponent來實現:

import { BrowserModule } from'@angular/platform-browser';
import { NgModule } from'@angular/core';
import { UpgradeModule, downgradeComponent } from'@angular/upgrade/static';
import { AppComponent } from'./app.component';
import { Ng2DemoComponent } from"ng2/app/ng2-demo.component";
declarevar angular: any;
angular.module('phonecatApp')
 .directive(
   'ng2Demo',
   downgradeComponent({component: Ng2DemoComponent})
 );
@NgModule({
 declarations: [
   AppComponent,
   Ng2DemoComponent
 ],
 imports: [
   BrowserModule,
   UpgradeModule
 ],
 entryComponents: [
   Ng2DemoComponent // Don't forget this!!!
 ],
 providers: [],
// bootstrap: [AppComponent] // No Bootstrap-Component
})
export class AppModule {
constructor(private upgrade: UpgradeModule) { }
 ngDoBootstrap() {
this.upgrade.bootstrap(document.body, ['phonecatApp'], { strictDi: true });
 }
}

就如你在例子中看到的,這個降級的組件在AngularJS 1.x模塊中註冊為一個指令。為了做到,我們利用全局的變量angular。為了告訴TypeScript這個已存在的變量,我們需要使用declare關鍵字。

之後,我們可以在AngularJS 1.x模板中調用Angular組件:

<!-- src/ng1/phone-list/phone-list.template.html -->
<div class="row">
<div class="col-md-2">
<!--Sidebar content-->
<p>
     Search:      <input ng-model="$ctrl.query" />
</p>
<p>
     Sort by:      <select ng-model="$ctrl.orderProp">
       <option value="name">Alphabetical</option>
       <option value="age">Newest</option>
    </select>
</p>
<p>
<!-- Angular 2 Component -->
<ng2-demo></ng2-demo>
</p>
</div>

如通常的AnguarJS中,我們在HTML文件中需要使用kebab慣例,而在JavaScript部分中註冊指令時使用正常的命名。後者使用駝峰命名法。

當我們重新加載應用,將會同時顯示AngularJS 1.x 電話列表和我們的Angular樣例組件:

你可能會好奇一個新的Angular組件怎麼使用AngularJS 1.x服務提供的應用邏輯,閱讀下一章節來獲得答案。

第四步:升級一個服務

為了能在一個新的Angular組件中使用既存的AngularJS 1.x服務,我們需要升級它。根據官方的文檔,我們必須要使用factory創建一個Angular服務provider。這個factory獲取一個AngularJS 1.x注入器($injector)的引用,並使用它獲取服務:

// src/ng2/app/phone.service.ts
import { InjectionToken } from"@angular/core";
export const PHONE_SERVICE = new InjectionToken<any>('PHONE_SERVICE');
export function createPhoneService(i) {
   return i.get('Phone');
}
export const phoneServiceProvider = {
 provide: PHONE_SERVICE,
 useFactory: createPhoneService,
 deps: ['$injector']
}

正常情況,在provide屬性中我們可以使用服務的類型作為依賴注入符號。但是在這個例子中,我們決定不對既有的AngularJS 1.x代碼升級到TypeScript,因此我們沒有任何類型。因此,這個例子使用了一個基於常量的符號叫做PHONE_SERVICE。在Angular 4+中提供的類型為InjectionToken,在Angular 2中我們可以使用OpaqueToken代替。InjectionToken使用一個類型參數來判斷它指向的服務類型。如提到的,我們沒有這個服務的類型,因此我們僅使用any。

這個討論的服務provider必須要在我們的Angular模塊中註冊:

// src/ng2/app/phone.service.ts
import { InjectionToken } from"@angular/core";
export const PHONE_SERVICE = new InjectionToken<any>('PHONE_SERVICE');
export function createPhoneService(i) {
   return i.get('Phone');
}
export const phoneServiceProvider = {
 provide: PHONE_SERVICE,
 useFactory: createPhoneService,
 deps: ['$injector']
}

之後,我們可以注入phoneService到我們的組件Ng2DemoComponent中,並使用它價值所有的電話信息:

import { Component, OnInit, Inject } from'@angular/core';
import { PHONE_SERVICE } from"ng2/app/phone.service";
@Component({
 selector: 'ng2-demo',
 template: `
   <h3>Angular 2 Demo Component</h3>    <img width="150" src="[...]" />    <p>      {{phones.length}} Phones found.    </p>  `
})
export class Ng2DemoComponent implements OnInit {
 phones: any[] = [];
constructor(
   @Inject(PHONE_SERVICE) private phoneService: any) {
   }
   ngOnInit() {
this.phones = this.phoneService.query();
   }
}

由於我們的符號是一個常量,這個實例使用Inject裝飾器來指向它。加載電話後,就可以顯示數量了。

重新加載應用後,我們可以看到:

注意我們有一個Angular 1.x的組件和一個Angular組件並使用AngularJS 1.x服務提供的數據進行顯示。

不僅僅是嵌套AngularJS 1.x和Angular的東西,我們還需要從各自的版本激活路由。下一節會處理相關內容。

第五步:導航到Angular組件

讓AngularJS 1.x的路由來激活Angular組件是很簡單的。我們僅需要配置一個路由的模板指向相應的模板即可:

$routeProvider.
 when('/phones', {
   template: '<phone-list></phone-list>'// AngularJS 1.x template
 }).
 when('/phones/:phoneId', {
   template: '<phone-detail></phone-detail>'// AngularJS 1.x template
 }).
 when('/ng2-demo', {
   template: '<ng2-demo></ng2-demo>'// Angular component
 })

這樣就允許使用Angular組件和AngularJS的路由一起使用,並可以和傳統的指令和組件一起使用。

這裡要強調一下,同樣使用流行的UI-Router。

這個方案簡單的同時,同時也有一個缺點:我們不能利用Angular路由來使用新寫的組件。為了讓這個成為可能,我們會實現Victor Savkin提出的Sibling Outlet approach,使兩種路由共存。實現的基礎是他提出的升級殼模式(Upgrade Shell pattern)。下兩章會介紹如何實現這裡的想法。

第六步:使用Victor Savkin的升級殼模式

Angular的主策劃之一Victor Savkin提出了升級殼模式。他在他的電子書和博客中描述了升級殼模式。它正視了Angular組件在混合應用的頂層。這是升級殼包含了AngularJS構建塊(指令、組件和控制器)和Angular組件。

為了實現這個模式,在開始實現文章中的努力時我們可以使用CLI生成的AppComponent:

// src/ng2/app/app.component.html
<!--The whole content below can be removed with the new code.-->
<div style="text-align:center">
<h1>
   Welcome to {{title}}!!
</h1>
</div>
<!-- ng1 -->
<div class="view-container">
<div ng-viewclass="view-frame"></div>
</div>
<!-- /ng1 -->

注意Angular組件中包含了AngularJS 1.x路由的ng-view。

為了讓這個組件作為我們應用的最頂層,我們需要直接啟動它。我們需要將它放到AppModule的bootstrap數組中:

// src/ng2/app/app.module.ts
import { BrowserModule } from'@angular/platform-browser';
import { NgModule, InjectionToken } from'@angular/core';
import { UpgradeModule, downgradeComponent } from'@angular/upgrade/static';
import { AppComponent } from'./app.component';
import { Ng2DemoComponent } from"ng2/app/ng2-demo.component";
import { phoneServiceProvider } from"ng2/app/phone.service";
declarevar angular: any;
angular.module('phonecatApp')
 .directive(
'ng2Demo',
   downgradeComponent({component: Ng2DemoComponent})
 );
@NgModule({
 declarations: [
   AppComponent,
   Ng2DemoComponent
 ],
 imports: [
   BrowserModule,
   UpgradeModule
 ],
 entryComponents: [
   Ng2DemoComponent // Don't forget this!!!
 ],
 providers: [
   phoneServiceProvider  ],
 bootstrap: [AppComponent]
})
export class AppModule {
// Remove code for bootstrapping hybrid app manually !!!
/*
 constructor(private upgrade: UpgradeModule) { }  ngDoBootstrap() {    this.upgrade.bootstrap(document.body, ['phonecatApp'], { strictDi: true });  }*/
}

請注意,我們也需要移除手動啟動應用的代碼。代碼被移動到AppComponent中,並在升級殼啟動後開始幹活。

// src/ng2/app/app.component.ts
import { Component, Inject } from'@angular/core';
import { PHONE_SERVICE } from"ng2/app/phone.service";
import { UpgradeModule } from"@angular/upgrade/static";
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 title = 'app';
  phones: any[] = [];
constructor(private upgrade: UpgradeModule) { }
   ngOnInit() {
this.upgrade.bootstrap(document.body, ['phonecatApp']);
   }
}

並且,確保index.html引用了我們的升級殼:

<!-- src/index.html -->
<body>
<app-root></app-root>
</body>

重新加載應用,並查看包含AngularJS 1.x應用的升級殼。

當這個開始工作,我們就提供了下一章目標的基礎:同時使用AngularJS 1.x和Angular路由。

第七步:使用Victor Savkin的兄弟姐妹出口來同時使用兩種路由

Victor Savkin的兄弟姐妹出口描述了一種同時使用兩個版本Angular的路由方法。為了實現這一點,我們需要加載Angular路由:

npm install @angular/router --save

之後,擴展app.component.html。它會各種路由獲取一個出口。針對AngularJS 1.x路由我們使用帶有ng-view的div,針對Angular路由是一個router-outlet元素:

<!-- src/ng2/app/app.component.html -->
<div class="view-container">
<div ng-viewclass="view-frame"></div>
<router-outlet></router-outlet>
</div>

當激活了一個基於AngularJS 1的路由,第一個獲得一個模板;當激活了一個Angular路由,後者被使用。

現在,讓我們配置Angular路由:

// src/ng2/app/app.module.ts
import { BrowserModule } from'@angular/platform-browser';
import { NgModule, InjectionToken } from'@angular/core';
import { RouterModule} from'@angular/router';
import { UpgradeModule, downgradeComponent } from'@angular/upgrade/static';
import { AppComponent } from'./app.component';
import { Ng2DemoComponent } from"ng2/app/ng2-demo.component";
import { phoneServiceProvider } from"ng2/app/phone.service";
declarevar angular: any;
angular.module('phonecatApp')
 .directive(
'ng2Demo',
   downgradeComponent({component: Ng2DemoComponent})
 );
@NgModule({
 declarations: [
   AppComponent,
   Ng2DemoComponent
 ],
 imports: [
   BrowserModule,
   UpgradeModule,
   RouterModule.forRoot([
     {
       path: '',
       pathMatch: 'full',
       redirectTo: 'ng2-route'
     },
     {
       path: 'ng2-route',
       component: Ng2DemoComponent
     }
   ],
   {
     useHash: true
   }
   )
 ],
 entryComponents: [
   Ng2DemoComponent
 ],
 providers: [
   phoneServiceProvider  ],
 bootstrap: [AppComponent]
})
export class AppModule {
}

就如你所看的,在這個例子中剛剛定義了Angular路由的配置。作為補充,為了兩個版本的一致性,這裡使用了哈希策略。

我們需要確保當AngularJS 1.x路由激活時,Angular路由不做任何事。為了做到這一點,Victor建議使用一個定製的UrlHandlingStrategy:

// src/ng2/app/app.module.ts
import { RouterModule, UrlHandlingStrategy } from'@angular/router';
[...]
export class CustomHandlingStrategy implements UrlHandlingStrategy {
 shouldProcessUrl(url) {
return url.toString().startsWith("/ng2-route") || url.toString() === "/";
 }
 extract(url) { return url; }
 merge(url, whole) { return url; }
}

這個策略需要註冊到*AppModule:

// src/ng2/app/app.module.ts
@NgModule({
 [...]
 providers: [
   phoneServiceProvider,
   { provide: UrlHandlingStrategy, useClass: CustomHandlingStrategy }
 ],
 bootstrap: [AppComponent]
})
export class AppModule {
}

之後,我們需要對AngularJS 1.x的路由配置做一些小修改。首先,我們必須要移除配置的哈希前綴,因為這會影響Angular路由。我們必須要使用otherwise加載一個空白模板來添加一個默認路由到版本1的出口中,當路由被其他路由處理的時候:

// src/app1/app.config.js
// No Prefix for the sake of uniformity
// $locationProvider.hashPrefix('!');
$routeProvider.
 when('/phones', {
   template: '<phone-list></phone-list>'
 }).
 when('/phones/:phoneId', {
   template: '<phone-detail></phone-detail>'
 }).
 when('/ng2-demo', {
   template: '<ng2-demo></ng2-demo>'
 })
 .otherwise({template : ''});

就如前面提的,使用AngularJS 1.x路由顯示的一切也對流行的UI-Router適用。

之後,添加一些菜單到AppComponent中來允許在基於AngularJS 1.x和Angular的路由間切換。

<!-- src/app2/app.component.html -->
<a routerLink="ng2-route">ng2-route</a> |
<a href="#/phones">Phones</a>

加載應用後,我們就可以在我們的路由間切換:

最後,為你推薦

【第1190期】完美升級 AngularJS 至 Angular

【第950期】Angular組件間通信

關於本文

譯者:@Perry
譯文:http://bookcell.org/2018/02/19/directly-upgrading-from-angularjs-to-angular-without-preparing-the-exiting-code-base/index.html
作者:@ManfredSteyer
原文:https://www.softwarearchitekt.at/post/2017/07/14/directly-upgrading-from-angularjs-1-x-to-angular-by-skipping-preparation.aspx

相關焦點

  • 通過5個簡單步驟升級到Angular 7
    升級到Angular 7隻需幾個簡單的步驟:首先,通過終端添加最新版本全局升級Angular版本:sudo npm install -g @angular/cli@latest在項目中本地升級版本,並確保新版本的更改反映在package.json文件中ng update @angular/cli升級package.json中的所有依賴項和dev依賴項依賴關係:npm install -
  • 使用 AngularJS & NodeJS 實現基於 token 的認證應用
    token-based-auth-backend在後端項目中,有三個主要文件:就是這樣!這個項目非常簡單,你不必深入研究就可以了解主要的概念。{ "name": "angular-restful-auth", "version": "0.0.1", "dependencies": { "express": "4.x", "body-parser": "~1.0.0", "morgan": "latest", "mongoose": "3.8.8",
  • Angular學習筆記(一)
    import { Router, NavigationExtras } from '@angular/router'constructor(private router: Router) {}1、js跳轉普通路由首先在頁面上定義一個按鈕用來模擬跳轉
  • Angular中sweetalert彈框的使用詳解,最全了!
    ,但是只能用sweetalert中的css,js必須通過npm下載sweetalert,引入下載的sweetalert.min.js二、版本說明Angular V1.2.30>Angular-sweetalert V1.0.4Sweetalert V2.1.0因為我們項目使用的angular版本較低,所以相對應下載的angular-sweetalert版本也低。
  • 在ASP.NET Core中使用Angular2,以及與Angular2的Token base身份認證
    相對於Angular1.x,借用某果的廣告語,唯一的不同,就是處處都不同。得益於徹底重構,性能相對於Angular1.x有了大幅提升,也更適合再全平臺部署。Angular2是基於Component的,Component可以理解為是1.x時代的Controller + $Scope + viewView的很多語法也做了更新,比如<li ng-repeat="movie in vm.movies"></li> 變成了 <li *ngFor="let
  • nw.js桌面程序自動更新(node.js表白記)
    喜慶的話不多說,今天給大家分享一個大致3周前,初次涉足Node.js實現的nw.js桌面程序的自動更新模塊吧。  本文不做教學,僅用於打臉!希望以此得到各位大神的幫助。  我本沒有打算寫如此博客來誤人子弟,這裡感謝@老畢(=^ ^=)  下面說的這個模塊是基於angular.js的,如此粗鄙的幾行代碼,還望各位同仁瞄眼之後便使勁的噴!
  • material2 發布 7.0.1,Angular 的 Material Design 風格框架
    Angular 的 Material Design 風格框架 material2 發布了 7.0.1 版本,這主要是一個 bug 修復版本:Bug 修復
  • Angular 2官方文檔導讀
    當你學會通過拷貝粘貼完成簡單功能之後,可以嘗試自己獨立添加路由,然後逐漸擴展到功能區(Angular模塊),最後你就可以嘗試自己開項目了。在這個過程中,你仍然要通讀一遍《英雄指南》教程。但是不用讀得特別細,更不用自己去試驗那些代碼。別忘了,在實戰層面有人幫你。你閱讀的目的只是對一些重要的技術點有印象,注意,不需要追求全記住。等將來遇到了,再憑記憶到文檔中查閱。
  • Vue.js 作者回應『Angular有哪些地方比Vue更優秀?』
    本文轉載自 Vue.js 作者尤雨溪的知乎專欄 —— 回應『Angular有哪些地方比Vue更優秀?』。
  • Angular 10 版本現已發布
    如何更新到版本10請訪問update.angular.io以獲取詳細信息和指導。為了獲得最佳的更新體驗,我們建議始終一次升級一個主要版本。更新:ng update @ angular / cli @ angular / core您可以在《更新到版本10指南》中閱讀有關此更新的更多信息。
  • Angular 4 指令快速入門
    指令的實現import { Directive, HostBinding} from '@angular/core';@Directive({    selector: '[greet]'})export class GreetDirective {  @HostBinding() innerText =
  • 前端框架 Angular 11.0.0 正式發布,不再支持 IE 9 、10
    Angular 11.0.0 將 TypeScript 升級到 4.0, 對 TypeScript 3.9 不再支持。 放棄了對 IE 9 、10 的支持。根據其官方博客介紹,主要更新如下:(1) 更新 Operation Byelog解決了 router 和 forms 的熱門問題(issues),並關閉一些其他第三方的熱門問題。 保證對新提出的 issues 兩周之內做出處理,並積極接受社區的貢獻。
  • SpreadJS 全面支持 Angular2,V10.2 版本即將發布
    詳細的操作步驟,請參考下面的博客http://blog.gcpowertools.com.cn/post/spreadjs-support-angular2.aspxSpreadJS V10.2 版本即將發布,更多更好的功能盡在新版本中,敬請期待!登錄 SpreadJS 官網,了解更多。
  • Angular2 架構總覽
    例如angular2/core、angular2/common、angular2/router、angular2/http。從Angular庫模塊中引入一些東西的格式是這樣的:import {Component} from 'angular2/core';之前引入AppComponent組件是這樣的:import {AppComponent} from '.
  • jQuery VS AngularJS 你更鍾愛哪個?
    譯文連結:http://www.codeceo.com/article/jquery-vs-angularjs.html 英文原文:7 JQuery Best Practices
  • angular 大型應用 - CSDN
    進行更改後測試CSS:假設在上面的步驟1中,您擁有一個完美的桌面視圖,然後開始使用移動視圖。 在使用行動裝置視圖之後,可以運行測試以確保在行動裝置上所做的任何更改都不會破壞桌面視圖。Now lets look at the backstopjs config file. Open up ./backstop.json 現在,讓我們看一下backstopjs配置文件。 打開.
  • Angular vs React 最全面深入對比
    Angular除了提供一些需要最新瀏覽器支持的功能外,同時提供以下標準功能:依賴注入模板路由(@angular/router)AJAX(@angular/http)表單(@angular/forms)組件化CSS封裝XSS保護單元測試工具功能豐富的好處就是你不需要額外費精力去挑選第三方的類庫
  • ionic2項目實戰教程 - 第2講 動態獲取抽屜分類菜單
    這一講包含的內容有: 1.組件(Component)的基本介紹2.定義服務組件(Service)3.在ionic2中使用網絡請求1.組件(Component)的基本介紹       這個組件是應用入口,啟動時做的一些初始化一般都在這裡調用,先分析下當前代碼,請看注釋。
  • Angular10教程--4.1 RxJs-創建類及合併類操作符
    ;const subscribe = promiseSource$.subscribe(val => console.log(val));import { from } from 'rxjs';const map = new Map([ [1, 'hi']]);map.set(2, 'Bye');map.set(3, 'rxjs