
Web開発の世界では、
Angular 2のベータ版
がリリースされました 。 また、リリース後にどのように見えるかについては、すでに想定することができます。
しかし、評価自体は、真空中で、製造業者のパンフレットにある電子機器の選択に似ています。 ガジェットにあるすべてのチップが記載されています。 そして、そこにないものはすべて言及されておらず、それらの存在について考えることすらできないかもしれません。 したがって、他の何かと比較して評価する方がはるかに効率的です。
そのため、Angular 2と新しい、しかし非常に野心的なプロジェクトである
Aureliaを比較するというアイデアが生まれました。 同時に、Habrの貯金箱にこのフレームワークに関する情報を補充します。これは、これまでのところ、Angular 2に関する情報よりもはるかに少ないためです。
ローンチの準備ができたプロジェクトの形式の記事の例のコードは
githubに投稿されています。 例はTypeScriptで記述されており、どちらも
systemjsを使用してい
ます 。 systemjsの構成は、各フレームワークのクイックスタートガイドから取られたものであり、まったく異なります。 フレームワークの作者が提供した形のままにしておくことは合理的であるように思われ、似たようなものにしようとしないでください。 また、プロジェクトで使用されている
httpサーバーはpushStateをサポートしていないことに注意してください(承認済みのプルリクエストがあるため、すぐにサポートされることを願っています)。したがって、Angularにハッシュベースのルーティングを含める必要がありました。
すべてのアーキテクチャ機能を徹底的に比較するのではなく、フレームワークを評価するのは、エンドユーザーがどのようなメリットを得るかを理解したいという観点からです。 1つの記事ですべてを比較しても機能しません。そのため、この記事は一般的な構造に精通しています。 そして、より難しい質問は第2部に残ります。
次のシナリオに従います。
- Aureliaの概要と、それをAngularと比較することが正当である理由を学ぶ
- 各航空写真の長所と短所を検討する
- 機能、用語、保存するものを指定しましょう
- 各フレームワークで最もシンプルなコンポーネントを作成しましょう
- ルーティングを構成する
- ネストされたコンポーネントを追加する
- 最も単純なデータバインディングオプションを検討する
- データバインディングで制御構造を考慮する
アウレリアとは何ですか?なぜAngularと比較するのが正当なのですか?
同じHabréのAureliaについての情報は
ほとんどないため、すべての読者がそれについて聞いたわけではないと想定できます。 ですから、オレリアの誕生の背景をお話しします。 さらに、それは非常に興味深く、少し劇的ですらあります。
Aureliaは、
Caliburn.Micro XAMLプラットフォーム向けの非常に人気のあるMV *フレームワークの作成者である
Rob Eisenbergのプロジェクトです。 彼は後に
Durandalと呼ばれるWeb用のMV *フレームワークを開発しました。 デュランダルはあまり人気がありませんでしたが、それでも非常に興味深くエレガントなソリューションがあり、フレームワークはそれを非常に愛するフォロワーの聴衆を集めました。
しかし、Rob EisenbergはDurandalのすべての欠点を理解していたため、彼のサポートとともに、
いわゆるNextGenフレームワークの開発に携わりました。
2014年1月、ngConfカンファレンスで、
John PapaはWeb開発の世界でよく知られ、DangrandalとNextGenフレームワークでRob Eisenbergによって提案され
たアイデアをAngularチームマネージャー
Brad Greenと共有しました。 これらのアイデアはグリーンに興味があり、アイゼンバーグと話をすることにしました。
会った後、ブラッド・グリーンとロブ・アイゼンバーグは、ウェブとウェブ開発の未来に対する彼らの見解が多くの点で一致していることに気づき、彼らは力を合わせることにし、アイゼンバーグはフレームワークの第2バージョンで
Angularチームで
働き始めました 。
しかし、10か月後、彼はAngular 2の開発の方向性が大きく変わりすぎて、彼が協力することに同意したAngular 2とは異なる
ため、Angularチームを辞めることにしました。
アイゼンバーグは短期間で、たとえば
スコット・アレンなどのスターを含むかなり大きなチームを編成し、夢の枠組みのもとに戻ってきました。 この仕事の結果
はアウレリアでした。
一般の人々はこのフレームワークを興味を持って受け入れました(評価時点で最も簡単な方法として、Aureliaはgithubで
5,000個の星を収集し
ましたが、Angular 2では
8,000 個の星を収集しました)。
Angular 2とAureliaで規定されている一般的な原則は非常に似ており、同じクラスのプレイヤーです。 しかし、詳細なビジョンと彼らが持っている機能のセットはまったく異なっているため、比較が興味深いものになっています。
Angular 2とAureliaの航空写真の長所と短所
フレームワークを選択するときに比較できる具体的な特性から、パフォーマンスを見てみましょう。
Aureliaはdbmonsterベンチマークで興味深い結果を示しており、
Angular 2よりわずかに優れたポイントを叩き、
Reactおよび
Angular1よりも顕著に優れています。
dbmonsterとはDbmonsterは、
Ryan Florenceによって開発されたレンダリングベンチマークです。 作業の速度を評価するために、絶えず更新されるデータを含む配列がレンダリングされます。これにより、フレームワークの速度を評価できます。 このテストは元々、Angular 1、Angular 2、React用に作成されました。 Aureliaの開発者の1人であるJeremy Danyowは、後
にAureliaの実装を導入しました 。
ベンチマークを評価するときは、次の点に注意することが役立ちます。
- スムーズなスクロール-ページは「ジャンプ」せずにスクロールする必要があります
- ツールチップ-マウスカーソルをリスト上に移動すると、ツールチップが描画されます。 スムーズに描画し、データを遅滞なく表示する必要があります。
- 再描画速度とメモリ速度-右下隅に2つのインジケータがあります。 最初は1秒あたりの再描画数を示し、2番目はメモリ消費量を示します
- データ変更の速度-ページの上部には、データ変更の頻度を調整できるスライダーがあります。 データの変更率が低下しても再描画率が増加しない場合、これは、問題のフレームワークが変更を非効率的に監視し、DOMの更新に関する決定を下すことを意味します。
すべてのインジケーターが正しく機能し、最も「クリーンな」結果を得るには、クロムブラウザーを使用し、次のコマンドで実行することをお勧めします。
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --user-data-dir="C:\chrome\dev-sessions\perf" --enable-precise-memory-info --enable-benchmarking --js-flags="--expose-gc"
無形の特性から、私は両方のフレームワークの最強と最弱の側面を評価しようとします(著者、私見)。
Angularの主な利点
- Angularのコミュニティは明らかに大きいため、アイデアや拡張機能が増え、既存の質問に対する答えを見つけやすくなります。
- Angularには3倍のチームがあり、プロジェクトの開発がはるかに高速です。 また、Angularチームは既に開発者ツールの作成者のサポートを確保しており、Angularのサポートは非常に多くのツールで行われます(また、開発者プレビューでも、既に動作する非常にクールなBatarangleがあります)。
アウレリアの主な利点
- Aureliaは、Angularと多くの興味深い機能を対比できます。 たとえば、これは高度な構成メカニズムであり、 テンプレートパーツです。 Aureliaは目立たないように設計されており、最終的なコードのフレームワーク設計の数は最小限です。 Aureliaはよりコンパクトで維持されますが、Angularはコピーペーストを強制的に生成することがあります。
- Aureliaチームは商用の顧客サポートを提供し、プロジェクトの方向性に影響を与える本当の機会があります。 また、Angular 2の場合、所有しているものを使用する必要があります。
Angularの主な欠点
- Angularの開発履歴を見ると、Angular 2が最終的にどうなるかをチームがはっきりと見ていないという印象を受けます。 私はAngular 2の作業の発表以来Angular 2をフォローしてきましたが、フレームワークは本当に非常に強力であり、常に順次変更されるわけではありません。 同じ理由で、アイゼンバーグはプロジェクトのアーキテクチャが元のアーキテクチャからどのように変わったのかのためにAngular 2チームを去りました。 同じ理由で、 同様の投稿が表示されます。
アウレリアの主な欠点
- アウレリアに関する主な質問は、彼女がAngular 2に反対するかどうかです。アイゼンバーグはアウレリアとAngular 2を対比しているため、これは怠questionな質問ではありません。さらに、 Angular 2の記事に関するコメントもあります。 私はアウレリアが本当に好きですが、著者が疲れているため、選択したフレームワークがいつかサポートされなくなる可能性が心配です。 一方、大きなFacebook がparse.comの閉鎖を発表してから1週間も経っていないため、誰も何の影響も受けません。
Angular 2とAureliaの機能、用語、保存するもの
Angular 2とAureliaのアーキテクチャは非常に似ています。 以下では、両方の作業の原則をいくつかの段落で定式化して、検討および比較するのに意味のある基本的な用語と構成を斜体で示します。 これが混乱した用語ではなく、読みやすいテキストになることを願っています。
Angular 2およびAureliaアプリケーションのコアは、対応する
テンプレートに関連付けられた
コンポーネントです。
アプリケーション(
app )を表すルートコンポーネントが必要
です 。
デコレータを使用して、メタデータをコンポーネントにバインドする必要があります。
コンポーネントの初期化は、
依存性注入を使用して実行されます。 また、各コンポーネントには、
ライフサイクルフックと統合できる宣言された
ライフサイクルがあり
ます 。 コンポーネントは階層構造に配置できます。
コンポーネントとテンプレート間の状態の同期と通信は、
データバインディングを使用して実行され
ます 。
パイプ (Angular)または
値コンバーター+バインディング動作 (Aurelia)を使用して、テンプレートを最終的なHTMLに埋め込むことができます。
ルーティングは 、アプリケーションの隔離された領域間を移動するために使用されます。
イベントは、アプリケーションモジュール間の通信に使用できます。
そして最後に、例に移ります。
最初のコンポーネントを作成する
角度2
まず、ルートコンポーネントとなる最も単純なコンポーネントを作成することから始めましょう。
import {Component} from 'angular2/core'; @Component({selector: 'angular-app', templateUrl: 'app/app.html'} }) export class App { message: string = 'Welcome to Angular 2!'; }
Angularがモジュールがコンポーネントであることを理解するには、@ Componentデコレーターでモジュールをラップする必要があります。
注-厳密に言えば、@ Componentはデコレーターではなくアノテーションです。 ここで違いについて読むことができます 。 記事では、Angular 2アノテーションのドキュメントでは「デコレータ」セクションにあるため、デコレータという用語は残しておきます。少なくとも、デコレータはセレクタをテンプレートを描画する場所を示す必要があります。 この場合、それは<angular-app>要素です。
テンプレートを宣言するための2つのオプションがあります。
- @ComponentデコレータのテンプレートパラメータとしてHTML文字列を指定します。 このアプローチは、テンプレートがコンパクトで、別のHTMLページを作成したくない場合に役立ちます。
- テンプレートのURLをtemplateUrlパラメーターとして指定します。 別のページが必要なので、このオプションを使用します
テンプレートは次のようになります。
<div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">{{message}}</a> </div> </div>
実際、これはコンポーネント全体です。 簡単です。
良いこと -コードは、Angular 1よりもフレームワーク自体の構造からよりクリーンで自由です。これは朗報です。
最も単純なコンポーネントであってもデコレータを使用する必要
があるのは
面倒です 。 ドキュメントから引用:
各Angularコンポーネントには、単一の@Componentと少なくとも1つのViewアノテーションが必要です。 @Componentアノテーションは、コンポーネントがインスタンス化されるタイミング、およびコンポーネントがバインドするプロパティとhostListenerを指定します。
この場合、この例で構成されたパラメーターは、ほとんどの場合、ある種のロジックに従います。明示的な構成の代わりに、規則を使用できます。より複雑なシナリオではデコレーターを接続する必要があります。
アウレリア
Aureliaは規約に基づいて構築されているため、コンポーネントはメタデータのない通常のモジュールです。
export class App { message: string = "Welcome to Aurelia!"; }
標準の規則に従って、テンプレートの宣言のために、コンポーネントに類似した名前のhtmlファイルを作成する必要があります。つまり、この例ではapp.htmlファイルになります。
<template> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">${message}</a> </div> </div> </template>
Aureliaの各テンプレートは、
テンプレート要素でラップする必要があります。 Angular 2と同様のインラインテンプレートを作成するには、
inlineViewデコレータを使用できます。 また、Aureliaでは、規則を変更し、高度なカスタマイズを実行できます。 詳細は
こちらをご覧ください 。
良いこと -コードは非常にクリーンで理解しやすいものです。 フレームワークの設計はありません。
何が気になる -あなたは同様の問題を解決するために多くの注釈を設定する必要があるかもしれません。 たとえば、これらはinlineView、noView、useView、useViewStrategyです。 ドキュメントはまだ十分ではなく、検索もされていないため、何をどこで使用するかについて単純に混乱するリスクがあります。
ルーティングを構成します
私たちの場合、各アプリケーションにはいくつかのページがあり、記事で概説されている側面が考慮されます。 AngularとAureliaの両方で、ルーティング自体と本質的に同じであるため、ネストされたルーティングは考慮しません。
角度2
Angular 2でルーティングを設定するには、@ RouteConfigデコレータをインポートし、ルートにバインドされるモジュールをインポートして、ルーティングマップを宣言する必要があります。 アプリコンポーネントでこれを行います。
... import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; import {BindingSample} from './binding-sample/binding-sample'; import {ComponentSample} from './component-sample/component-sample'; ... @RouteConfig([ { path: '/component-sample', name: 'ComponentSample', component: ComponentSample, useAsDefault: true }, { path: '/binding-sample', name: 'BindingSample', component: BindingSample } ]) export class App { ... }
各ルートについて、以下を示します。
- ルートパターン
- ルート名(マークアップでのバインドに必要)
- ルートがアクティブ化されたときにAngularが作成するコンポーネントモジュール
- これがデフォルトルートであることを示すuseAsDefaultオプションパラメータ
開始時にすでにルートがあるすべてのモジュールをロードする必要があることに混乱している場合は、非同期ロードを使用できます。 これを行うには、コンポーネントパラメーターの代わりに、ローダーパラメーターを使用して、目的のモジュールをインポートするプロミスを返す関数を指定します。 そうしますが、コード例は少し後です。
テンプレートでルーティングを使用してナビゲーションを描画し、現在のコンポーネントを描画するセクションを示すには、ROUTER_DIRECTIVESディレクティブのコレクションを追加インポートし、@ Componentデコレーターのディレクティブパラメーターに追加する必要があります。 合計で、app.tsモジュールは次のようになります。
import {Component} from 'angular2/core'; import {View} from 'angular2/core'; import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; @Component({ selector: 'angular-app', templateUrl: 'app/app.html', directives: [ROUTER_DIRECTIVES] }) @RouteConfig([ { path: '/component-sample', name: 'ComponentSample', loader : () => System.import('app/component-sample/component-sample').then(m => m.ComponentSample), useAsDefault: true }, { path: '/binding-sample', name: 'BindingSample', loader : () => System.import('app/binding-sample/binding-sample').then(m => m.BindingSample) } ]) export class App { message: string = "Welcome to Angular 2!"; }
次に、app.htmlにナビゲーションを追加します。 これを行うには、
routerLinkディレクティブを使用し、パラメーターとして配列を渡します。その最初の要素は、@ RouteConfigのセットアップ時に指定したルート名を含む文字列です。
… <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="active"> <a [routerLink]="['ComponentSample']">Component sample</a> </li> <li> <a [routerLink]="['BindingSample']">Binding sample</a> </li> </ul> </div> ...
ネストされたルーティングの場合、パラメーターは配列です。その後、ルートの名前を含む数行の配列を渡します。
ルートをパラメーター化する必要がある場合、パラメーターを持つオブジェクトは配列の最後の要素によって送信されます。
... <a [routerLink]="['BindingSample', {someParameter: 'someString'}]">Binding sample</a> ...
そして最後の瞬間。 現在のルートのテンプレートが描画される領域をマークアップで示す必要があります。 同じapp.htmlでrouter-outletディレクティブを使用してこれを行います。
<div class="container"> <router-outlet></router-outlet> </div>
良いこと -新しいルーティングは、Angular 1.xに存在していたrouteProviderよりも優れていますが、それでも多くの疑問が生じます。 ドキュメント内のルーティングに関連するほとんどのタイプにはまだ説明がまったくないため、明確に説明することは困難です。
混乱させるもの -いくつかのことを混乱させます。 まず第一に、これはデコレータを介して設定する必要があります-たとえば、アプリケーションに50のルートがある場合、モジュールのコードはこれらすべての設定で単純に失われます。 また、ナビゲーションスキームを構築するときにif-logicが必要な場合、コードが悪夢になるリスクがあります。
2つ目は、ルートのコレクション全体への明示的なアクセスがないことです。これは、各リンクを手動でレンダリングするのではなく、マークアップで簡単にソートしてナビゲーション全体をレンダリングできます(忘れます)。 繰り返しますが、ルートを構築するためのif-logicがある場合、テンプレートにこのロジックを複製して、あまり多く描画しないようにする必要があります。
アウレリア
Aureliaの規約に従って、コンポーネントのルーティングを構成するには、configureRouterメソッドを実装する必要があります。このメソッドはAureliaによって自動的に呼び出されます。 ネストされたルーティングにも同じことが言えます。configureRouterメソッドを持つコンポーネントは、ルーティングスキームを形成します。
export class App { message: string = "Welcome to Aurelia!"; router: any; configureRouter(config, router) { config.title = 'Welcome to Aurelia!'; config.map([ { route: ['', 'component-sample'], moduleId: 'app/component-sample/component-sample', nav: true, title: 'Component sample' }, { route: 'component-sample', moduleId: 'app/binding-sample/binding-sample', nav: true, title: 'Binding sample' } ]); this.router = router; } }
各ルートについて、以下を示します。
- ルートパターン(または一連のパターン、空白行パターンはデフォルトルートを意味します)。
- ルートをアクティブにするときに開始するモジュールの識別子。
- オプションのタイトルプロパティ-ルートをアクティブにすると、その値がページタイトルに追加されます。
- オプションのnavプロパティ-ルートをナビゲーションモデルに含めるかどうかを指定します。 数値を指定する場合、ナビゲーションモデルコレクション内の要素の順序を意味します。
転送された構成に基づいて、Aureliaはナビゲーションモデルを作成します。これはテンプレート内でソートされ、ナビゲーションをレンダリングできます。
<div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li repeat.for="row of router.navigation" class="${row.isActive ? 'active' : ''}"> <a href.bind="row.href">${row.title}</a> </li> </ul> </div>
最後のステップは、現在のルートのテンプレートが描画されるエリアをマークアップで示すことです。 同じapp.htmlでrouter-viewディレクティブを使用してこれを行います
<div class="container"> <router-view></router-view> </div>
良いこと -セットアップは簡単で、非常に明白です。 Aureliaが私たちを助けようとし、ナビゲーション用のコレクションを構築しているのは素晴らしいことです。
紛らわしいこと -ナビゲーションと比較して、Durandalはルート設定に任意のプロパティを追加する機能を削除しました。 一方で、これは、nefigであるため、もちろん正しいです。 一方、これにより、手動レンダリングの方向でナビゲーションモデルを使用する可能性が大幅に減少します。 メニュー項目にタイトルだけでなく、たとえばツールチップも追加する場合、ナビゲーションモデルは役に立ちません。
ネストされたコンポーネントを追加する
角度2
テストプロジェクトでネストされたコンポーネントを操作する例については、コンポーネントサンプルフォルダーがあり、必要なものがすべて含まれています。
したがって、Angular 2でネストされたコンポーネントを作成するには、次が必要です。
- コンポーネントを宣言し、メタデータをバインドします。 親コンポーネントのデータを使用してプロパティを初期化するには、@ Componentデコレータに入力パラメータを追加し、対応するプロパティの名前を渡します。
import {Component} from 'angular2/core'; @Component({ selector: 'test-child-component', inputs: ['inputMessage'], template: `<div class="panel panel-default"> <div class="panel-heading">Child component title</div> <div class="panel-body"> Message from parent component is: {{inputMessage}} </div> </div>` }) export class TestChildComponent { inputMessage: string }
- 親コンポーネント(component-sample.ts)に子コンポーネントをインポートし、@ Componentデコレーターのディレクティブ配列に渡します
- 親コンポーネントのテンプレートに、ネストされたコンポーネントから指定されたセレクターに対応する要素を配置し、パラメーターを渡します
その結果、親コンポーネントは次のようになります。
import {Component} from 'angular2/core'; import {TestChildComponent} from './test-hild-omponent'; @Component({ template: ` <div class="sample-header"> <h1>{{message}}</h1> </div> <test-child-component [inputMessage]="messageForChild"></test-child-component>`, directives: [TestChildComponent] }) export class ComponentSample { message: string = 'This is a component with child component sample'; messageForChild: string = 'Hello to child component!'; }
良いこと -一般的に、すべてがシンプルで明確です。
あなたが悩むのは、アウレリアが持っている素敵なパンがないことです。 以下に説明します。
アウレリア
Aureliaでは、カスタム要素と構成という2つの方法でネストされたコンポーネントを描画できます。
一般に、最初の方法はAngular 2に似ており、複雑なコントロールの作成などに使用されます。 テストプロジェクトコードでは、このアプローチはtest-custom-element.htmlファイルで示されています。
2番目は主にマスター詳細スクリプトに使用され、より柔軟です。これは、ロードするコンポーネント、描画するテンプレート、転送するデータを動的に示すことができるためです。 このアプローチは、ファイルtest-hild-component.tsのテストプロジェクトで実証されています。
両方のオプションを順番に分析します。
オプション1-カスタム要素:
カスタム要素を使用してネストされたコンポーネントを作成するには、次のものが必要です。
- 通常のコンポーネントを作成し、さらにデコレータプロパティで@bindableをマークします。パラメータとしてテンプレートを通過する値(Angular 2の入力パラメータに似ています)。 さらに、要素が単純で動作しない場合は、コンポーネントを作成せずに、テンプレートを作成し、同じ名前の属性を使用してバインド可能なプロパティを一覧表示するだけで済みます。 Aureliaコンポーネントは「オンザフライ」で作成します:
<template bindable="message"> <div class="panel panel-default"> <div class="panel-heading">Custom element title</div> <div class="panel-body"> Message from parent component is: ${message} </div> </div> </template>
- 必要なモジュールを指す親コンポーネントのテンプレートにrequire要素を追加し(Angular 2のディレクティブパラメーターに似ていますが、テンプレート内)、必要な場所にマークアップでカスタム要素を描画します。 パラメーターは、<property name> .bind属性を使用して渡されます。 その結果、親コンポーネントのテンプレートは次のようになります。
<template> ... <require from="app/component-sample/test-custom-element.html"></require> <test-custom-element message.bind="messageForCustomElement"></test-custom-element> </template>
要素が普遍的に使用される場合、グローバルリソースとして登録できます。 これにより、各テンプレートに<require ...>を記述できなくなります。 その方法について
は 、「リソースのグローバル化」セクションに記載されています。
Aureliaには、Angularで見つけることができなかったもう1つの優れたオプションとして、親テンプレートからマークアップを渡す方法があります。 要素test-custom-element内の親テンプレートでマークアップを宣言し、子で要素を追加する場合
<content></content>
次に、親テンプレートからのマークアップが子に描画されます。 また、カスタム要素を使用する場合、前述の
テンプレートパーツを使用して、いくつかの交換可能な領域を宣言できます。
良いこと -すべてがシンプルで論理的です。
気になること -誰もがマークアップで依存関係を宣言する必要があるとは限りません。
オプション2-構成:
コンポジションを使用してネストされたコンポーネントを作成するには、次のものが必要です。
- 通常のコンポーネントを作成します。 composeは弱く接続されたコンポーネントを想定しているため、データ転送にライフサイクルフックを使用する必要があります (Angular 2にもこれらがありますが、次の記事ではそれらについて)。 この場合、activateメソッドを使用します。 テンプレートは小さいので、インラインにします。
import {inlineView} from 'aurelia-templating'; @inlineView('<template><h3>${inputMessage}</h3><template>') export class TestChildComponent { inputMessage: string; activate(inputMessage: string) { this.inputMessage = inputMessage; } }
- 親要素のテンプレートに、compose要素を配置します。この要素には、子コンポーネントを持つモジュールの識別子を示します。 親コンポーネントから子にデータを転送するには、model.bind属性を使用します。
<compose model.bind="messageForChild" view-model="app/testChildComponent"></compose>
これは良いことです -私の意見では、composeはプロジェクトの複雑さに対処するための非常にクールな方法です。 柔軟性を高めながら、コンポーネント間の分離を提供します。
何が気になる -私は長い間この項目について考えましたが、私は何も書くことができませんでした。 私は文句を言うことは何もありません。
データバインディング
角度2
Angularチームが新しいデータバインディングの開発で行った主な作業は、使用するディレクティブの数を最小限に抑え、データ移動の方向を明確に区別することでした。DOMへ、DOMから、双方向。 順番にすべてを見てみましょう。
DOMへ
DOMへの単方向バインディングは、2つの形式を使用して実行されます。
文字列補間:
<div class="panel-body"> This string is builted with {{interpolationString}} syntax </div>
およびプロパティのバインド:
<img [src]="iconUrl" />
文字列補間の場合、二重山括弧で囲まれたテキストは式として評価され、実行され、その結果がテンプレートに配置されます。 つまり、コンポーネントのプロパティだけでなく、この種の式をバインドすることもできます。
<h1>2 = {{1+1}}</h1>
ただし、この機能を乱用せず、複雑な式をコンポーネントのプロパティに入れないことをお勧めします。
プロパティバインディングの場合、キーは角かっこです。これは、テンプレートエンジンに、これが式の結果を右に割り当てるプロパティの名前であることを通知します。このフォームでは式もサポートされていますが、乱用はお勧めしません。標準のプロパティに加えて、routerLink、textContentなどの追加のディレクティブセットがあります。注-Angular 2でテンプレートを開発する場合、実際にはHTMLではなく、特別なAngular 2構文で記述しますテンプレートを解析するには、独自のパーサーを使用します。そして、あなたが書くとき、例えば:
<input value="some text" />
これは、属性に値が割り当てられる「純粋な」HTMLではなく、定数の割り当てに分解される構文糖衣です。
<input [value]="'some text'" />
重要な点は、データを属性、クラス名、およびスタイルにバインドするために、クラス、スタイル、およびattrプレフィックスを使用する別個の構文が必要であることです。 たとえば、次のように:
<img [style.width]="iconWidth" [style.height]="iconHeight" [src]="iconUrl" />
スタイルの複数のプロパティまたは複数のクラスを同時に設定するためのngClassおよびngStyleディレクティブがあります。式の結果として、各プロパティがスタイルプロパティまたはクラス名として評価されるオブジェクトを期待します。プロパティバインディングを属性バインディングから分離するポイントは、html属性とDOM要素のプロパティに明確な違いがあることです。属性は要素を初期化するために使用され、プロパティは要素の状態を変更するために使用されます。属性を使用するのはAngular 2です。ドムから
この場合、すべてがシンプルです。これはイベントハンドラーのバインドです。 <input type="button" (click)="onClicked()" value="Click me!" />
このバージョンのキーは括弧で、その中にイベントの名前を書きます(「on」プレフィックスなし)。バインディングの右側の式の中では、$イベント変数が使用可能です。これは実際にはDOMイベントです。これにより、最も単純なハンドラーに対して個々の関数を宣言せず、インライン式を記述できません。ただし、繰り返しますが、この方法で複雑な構造に関与して記述しても意味がありません。両方向
実際、双方向のデータバインディングは、DOMからDOMへの組み合わせを使用して実行できます。 <input [value]="twoWayBindedProperty" (input)="twoWayBindedProperty=$event.target.value" />
ただし、これは非常に典型的なシナリオであるため、Angularチームは特別なngModelディレクティブを開発しました。 <input [(ngModel)]="twoWayBindedProperty" />
必要に応じて、全体を個別の部分に分解し、DOMからの指示のためにngModelChangeディレクティブが必要です。 <input [ngModel]="twoWayBindedProperty" (ngModelChange)="twoWayBindedProperty=$event">
注:[]、()b [()]の構文と混同されており、標準オプションを好む場合、接頭辞bind-、on-、bindon-をそれぞれ使用できます。例: <img bind-src="iconUrl">
これは良いことです-控えめに言っても、構文が異常であり、彼に向けられた多くの否定的な声明が既にあるという事実にもかかわらず、私は彼が個人的に好きです。まず、それは非常に顕著です。第二に、覚えやすいことです。第三に、彼はさまざまな編集者のインテリセンスと良い友達になります。これは最初のキャラクターから、これがAngular 2コンストラクトであることは明らかであり、すぐにディレクティブオプションを受け取り、これらのngClass、ngModelなどをすべて覚える必要はありません 第4に、これらすべての括弧に完全にうんざりしている場合は、標準形式に変更できます。混乱すること-Aureliaとは対照的に、1回限りの拘束力とイベント委任の可能性は十分ではありません。しかし、これらのことは一般的なケースでは重要ではありません。アウレリア
Aureliaのデータバインディングは、データの移動方向の微調整に重点を置いています。フレームワークはいくつかの合理的な仮定を行いますが、開発者は自分で決定する機会を残します。最終的に、次のオプションがあります。文字列補間
<div class="panel-body"> This string is builted with ${interpolationString} syntax </div>
Angular 2の文字列補間と同様に、構文のみが異なります({{}}ではなく$ {}):プロパティのバインド
式<property name>。<Binding type> = "expression"に短縮されます。バインディングのタイプは次のとおりです。- .bind-適用場所に応じて決定します。入力要素には双方向バインディングが使用され、他のすべての場合には一方向バインディングが使用されます
- .one-way-AngularのDOMに類似
- .two-way-クラシックな双方向バインディング
- .one-timeは、変更を追跡せずに1回限りのデータレンダリングを行うためのオプションです。可能な限りリソースを節約します。典型的な使用例は、読み取り専用モードでデータを含むリストを描画することです。
明らかに、一般にプロパティバインディングの構文は次のとおりです。 <input value.bind="iconUrl" />
Angular 2のように標準プロパティをバインドすることに加えて、innerHTML、textContent、styleのカスタム属性があります。.bindを追加してプロパティを指定する場合と、.bindを使用せずに文字列補間を使用する場合の2つのスペルオプションがあります。 <div innerhtml.bind="htmlProperty"></div> <div innerhtml="${htmlProperty}"></div>
イベントハンドラー
イベントハンドラをバインドするには、2つのオプションがあります。- .trigger-要素に直接バインドされたハンドラーを作成します
- .delegate — , document ( shadow DOM) , , . . , , bubbling (, , - binding-sample.html).
Angular 2のように、ハンドラー式内のイベントにアクセスするには、$イベント変数を使用できます。注:NDCロンドンでのスピーチで、アイゼンバーグは、Aurelia構文はプラグインで簡単に書き換えることができ、Angular 2構文を使用してAureliaでのデータバインディングを示していますが、このプラグインはどこにも見つかりませんでした。
良いのは、必要に応じて微調整できることです。バインドオプション1回。HTML標準との完全な互換性。面倒なのは、一回限り、一方向、双方向のオプションの詳細な構文です。また、IntelliSenseのサポートは、Angularほどクールではありません。データバインディングの制御構造
角度
制御構造(for、if、switch)
読者はすでに疲れ始めていると思うので、詳細には触れません。一般的な構文を見てください: <div class="panel-body"> Select something: <select [(ngModel)]="selectedClass"> <option *ngFor="#alertClass of alertClasses" [value]="alertClass">{{alertClass}}</option> </select> </div> <div class="panel-body"> <div [ngSwitch]="selectedClass"> <template [ngSwitchWhen]="'success'"> <div class="alert alert-success" role="alert">You will be successfull if you learn Angular</div> </template> ... <template ngSwitchDefault>You must choose option</template> </div> <div *ngIf="selectedClass=='success'"> <div class="alert alert-success" role="alert">Extra message with *ngIf binding</div> </div> </div>
一般的に、異常なことは何もありません。注意すべきは、ngForとngIfの構文です。*文字がディレクティブの前にあります。ドキュメントで説明されているように、これはテンプレート要素でテンプレートをラップすることを避ける一種の構文糖です。テンプレートでローカル変数を作成する
ローカル変数は、htmlテンプレートのさまざまな領域のデータにアクセスするために必要です。ngForループで既に見た変数を作成する最も簡単な例: <option *ngFor="#alertClass of alertClasses" [value]="alertClass">{{alertClass}}</option>
特殊文字#を使用して、テンプレート内でアクセスする変数を宣言していることをAngularに示しました。現在の配列要素のインデックスを示す変数を作成することもできます。 <option *ngFor="#alertClass of alertClasses, #index=index" [value]="alertClass">{{index}} {{alertClass}}</option>
#(または正規の代替「val-」)を使用した変数の別の宣言は、ngForループの外側に適用できます。この場合、変数は変数が宣言されたhtml要素を指します。この変数は、たとえばイベントハンドラーで使用できます。しかし、テンプレートでは、そのような変数は機能しません。つまり、監視は実行されません。 <input #i placeholder="Type something"> <input type="button" class="btn btn-success" (click)="displayTextboxValue(i.value)" value="And click" /> <br/> But templating doesn't work with it - {{i.value}}
アウレリア
制御構造(for、if、show)
Aureliaスイッチが実装されていないという事実から始める価値があります(少なくとも現時点では)。また、Aureliaの用語では、制御構造はデータバインディングを指すのではなく、先ほど見た構成のようにHTML拡張を指すことに注意してください。全体として、制御構造から、会社のためにここに描かれている繰り返し、もし、表示します: <div class="panel-body"> Select something: <select value.bind="selectedClass"> <option repeat.for="alertClass of alertClasses" value.bind="alertClass">${alertClass}</option> </select> </div> <div class="panel-body"> <div if.bind="selectedClass=='success'" class="alert alert-success" role="alert">You will be successfull if you learn Aurelia</div> ... <div show.bind="selectedClass=='success'"> <div class="alert alert-success" role="alert">Extra message with show extension</div> </div> </div>
さらに、repeat内で式を記述する場合、次の変数を使用できます。- $ index-配列内の現在の要素のインデックス
- $ first-これが配列の最初の要素であれば真
- $ last-これが配列の最後の要素であれば真
- $ even-配列内の偶数要素である場合はtrue
- $ odd-配列の奇数要素の場合はtrue
テンプレートでローカル変数を作成する
上記のrepeat内でローカル変数を作成するための構文は既に見ました。Angular 2と比較するために、HTML要素を指す変数を作成する方法を確認する必要があります。これにはref属性が使用されます。作成された変数は、イベントハンドラーとテンプレートの両方で使用できます。つまり、監視が実行されます。 <div class="panel-body"> <input ref="i" placeholder="Type something"> <input type="button" class="btn btn-success" click.delegate="displayTextboxValue(i.value)" value="And click" /> <br/> And templating works with it - ${i.value} </div>
恥ずかしいこと -気配りのある読者は、Angular 2の部分に「何が良いのか-恥ずかしいのか」というメモがないことに気付くことがあります。私はこのセクションを結合し、両方について書くことにしました、なぜならそれらには1つの問題があるからです。この問題は、テンプレートにエラーがある場合、常に両方のエラーがスローされることではありません。たとえば、両方のフレームワークのifの例でプロパティ名を誤って記述しようとすると、両方が静かに動作し続けます。そのため、私たちは間違いやタイプミスを抱えています。以上です。
読んでくれてありがとう:)