apeescape2.com
  • メイン
  • トレンド
  • リモートの台頭
  • 技術
  • 製品ライフサイクル
Webフロントエンド

Ember.js開発者が犯す8つの最も一般的な間違い

Ember.js は、複雑なクライアント側アプリケーションを構築するための包括的なフレームワークです。その信条の1つは「設定より規約」であり、ほとんどのWebアプリケーションに共通する開発の大部分があり、したがってこれらの日常的な課題のほとんどを解決するための単一の最良の方法であるという信念です。ただし、適切な抽象化を見つけ、すべてのケースをカバーするには、時間とコミュニティ全体からの入力が必要です。推論が進むにつれ、解決策を見つける必要があるときに手を挙げて誰もが自分で身を守るのではなく、時間をかけてコア問題の解決策を正しく取得し、それをフレームワークに焼き付ける方がよいでしょう。

Ember.jsは常に進化しています 開発がさらに簡単 。ただし、他の高度なフレームワークと同様に、Ember開発者が陥る可能性のある落とし穴がまだあります。次の投稿で、これらを回避するためのマップを提供したいと思います。さっそく始めましょう!

よくある間違いその1:すべてのコンテキストオブジェクトが渡されたときにモデルフックが起動することを期待する

アプリケーションに次のルートがあると仮定します。



Router.map(function() { this.route('band', { path: 'bands/:id' }, function() { this.route('songs'); }); });

bandルートには動的セグメントidがあります。アプリに/bands/24、24などのURLが読み込まれる場合modelに渡されます対応するルートのフックband。モデルフックには、セグメントを逆シリアル化して、テンプレートで使用できるオブジェクト(またはオブジェクトの配列)を作成する役割があります。

// app/routes/band.js export default Ember.Route.extend({ model: function(params) { return this.store.find('band', params.id); // params.id is '24' } });

ここまでは順調ですね。ただし、ブラウザのナビゲーションバーからアプリケーションをロードする以外に、ルートを入力する方法は他にもあります。そのうちの1つはlink-toを使用していますテンプレートからのヘルパー。次のスニペットは、バンドのリストを調べて、それぞれのbandへのリンクを作成します。ルート:

{#each bands as } {{link-to band.name 'band' band}} {{/each}}

link-toの最後の引数bandは、ルートの動的セグメント、つまりそのidを埋めるオブジェクトです。ルートのIDセグメントになります。多くの人が陥る罠は、モデルがすでにわかっていて渡されているため、その場合はモデルフックが呼び出されないことです。それは理にかなっており、サーバーへの要求を保存する可能性がありますが、確かにそうではありません。直感的。それを回避する独創的な方法は、オブジェクト自体ではなく、そのIDを渡すことです。

{band} {{link-to band.name 'band' band.id}} {{/each}}

Ember.js

エンバーの緩和計画

ルーティング可能なコンポーネントがまもなくEmberに登場します。 おそらくバージョン2.1または2.2 。それらが着陸すると、動的セグメントのあるルートにどのように移行しても、モデルフックは常に呼び出されます。対応するRFCを読む ここに 。

よくある間違いその2:ルート駆動型コントローラーがシングルトンであることを忘れる

Ember.jsのルートは、対応するテンプレートのコンテキストとして機能するコントローラーにプロパティを設定します。これらのコントローラーはシングルトンであるため、コントローラーがアクティブでなくなった場合でも、コントローラーで定義された状態は保持されます。

これは非常に見落としがちなものであり、 私もこれに出くわしました 。私の場合、バンドと曲を含む音楽カタログアプリがありました。 songCreationStarted songsのフラグコントローラは、ユーザーが特定のバンドの曲の作成を開始したことを示しました。問題は、ユーザーが別のバンドに切り替えた場合、songCreationStartedの値がしつこく、半分完成した曲は他のバンドのためのもののようで、混乱していました。

勘定科目表の設計のベストプラクティス

解決策は、残したくないコントローラーのプロパティを手動でリセットすることです。これを行うための1つの可能な場所はsetupControllerです。対応するルートのフック。afterModel以降のすべての遷移で呼び出されます。フック(その名前が示すように、modelフックの後にあります):

// app/routes/band.js export default Ember.Route.extend({ setupController: function(controller, model) { this._super(controller, model); controller.set('songCreationStarted', false); } });

エンバーの緩和計画

繰り返しますが、の夜明け ルーティング可能なコンポーネント この問題を解決し、コントローラーを完全に終わらせます。ルーティング可能なコンポーネントの利点の1つは、ライフサイクルがより一貫しており、ルートから移行するときに常に破棄されることです。彼らが到着すると、上記の問題は消えます。

よくある間違いその3:setupControllerでデフォルトの実装を呼び出さない

Emberのルートには、アプリケーション固有の動作を定義するためのライフサイクルフックがいくつかあります。すでに見ましたmodelこれは、対応するテンプレートのデータをフェッチするために使用され、setupControllerは、コントローラー、テンプレートのコンテキストを設定するために使用されます。

この後者のsetupControllerには、modelからモデルを割り当てるという賢明なデフォルトがあります。 modelとしてフックしますコントローラのプロパティ:

// ember-routing/lib/system/route.js setupController(controller, context, transition) { if (controller && (context !== undefined)) { set(controller, 'model', context); } }

(contextは、上記のember-routingと呼ぶもののmodelパッケージで使用される名前です)

モンテカルロシミュレーションの構築方法

setupControllerフックは、コントローラーの状態をリセットするなど、いくつかの目的でオーバーライドできます(上記のよくある間違い2のように)。ただし、上記でEmber.Routeにコピーした親実装を呼び出すのを忘れた場合、コントローラーにmodelがないため、長いヘッドスクラッチセッションに参加する可能性があります。プロパティセット。したがって、常にthis._super(controller, model)を呼び出します。

export default Ember.Route.extend({ setupController: function(controller, model) { this._super(controller, model); // put the custom setup here } });

エンバーの緩和計画

前に述べたように、コントローラー、およびそれらとともに、setupControllerフックはすぐになくなるので、この落とし穴はもはや脅威ではありません。ただし、ここで学ぶべきより大きな教訓があります。それは、祖先での実装に注意することです。 init Emberのすべてのオブジェクトの母であるEmber.Objectで定義されている関数は、注意が必要なもう1つの例です。

よくある間違いその4:this.modelForの使用親以外のルートを使用する

Emberルーターは、URLを処理するときに、各ルートセグメントのモデルを解決します。アプリケーションに次のルートがあると仮定します。

Router.map({ this.route('bands', function() { this.route('band', { path: ':id' }, function() { this.route('songs'); }); }); });

/bands/24/songsのURLが与えられると、model bands、bands.bandのフックそしてbands.band.songsこの順序で呼び出されます。ルートAPIには特に便利なメソッドmodelForがあり、そのモデルはその時点で確実に解決されているため、子ルートで使用して親ルートの1つからモデルをフェッチできます。

たとえば、次のコードは、bands.bandでバンドオブジェクトをフェッチするための有効な方法です。ルート:

// app/routes/bands/band.js export default Ember.Route.extend({ model: function(params) { var bands = this.modelFor('bands'); return bands.filterBy('id', params.id); } });

ただし、よくある間違いは、modelForでルート名を使用することです。 ない ルートの親。上記の例のルートがわずかに変更された場合:

Router.map({ this.route('bands'); this.route('band', { path: 'bands/:id' }, function() { this.route('songs'); }); });

bandsのように、URLで指定されたバンドをフェッチするメソッドは壊れます。 routeは親ではなくなったため、そのモデルは解決されていません。

// app/routes/bands/band.js export default Ember.Route.extend({ model: function(params) { var bands = this.modelFor('bands'); // `bands` is undefined return bands.filterBy('id', params.id); // => error! } });

解決策はmodelForを使用することです親ルートの場合のみ、modelForの場合は他の手段を使用して必要なデータを取得しますストアからのフェッチなどは使用できません。

// app/routes/bands/band.js export default Ember.Route.extend({ model: function(params) { return this.store.find('band', params.id); } });

よくある間違いその5:コンポーネントアクションが実行されるコンテキストの間違い

ネストされたコンポーネントは、常にEmberで最も推論が難しい部分の1つです。の導入に伴い Ember1.10のブロックパラメータ 、この複雑さの多くは軽減されましたが、多くの状況では、子コンポーネントから起動されたアクションがトリガーされるコンポーネントを一目で確認するのは依然として困難です。

band-listがあるとしましょうband-list-itemsを持つコンポーネントその中に、各バンドをリストのお気に入りとしてマークすることができます。

// app/templates/components/band-list.hbs {band} {{band-list-item band=band faveAction='setAsFavorite'}} {{/each}}

ユーザーがボタンをクリックしたときに呼び出されるアクション名がband-list-itemに渡されます。コンポーネントであり、そのfaveActionの値になりますプロパティ。

band-list-itemのテンプレートとコンポーネントの定義を見てみましょう。

// app/templates/components/band-list-item.hbs {{band.name}} Fave this // app/components/band-list-item.js export default Ember.Component.extend({ band: null, faveAction: '', actions: { faveBand: { this.sendAction('faveAction', this.get('band')); } } });

ユーザーが「これをお気に入りに追加」ボタンをクリックすると、faveBandアクションがトリガーされ、コンポーネントのfaveActionが起動されます渡されたもの(上記の場合はsetAsFavorite)、 親コンポーネント上 、band-list。

これは、ルート駆動型テンプレートからのアクションがコントローラー上で実行されるのと同じ方法でアクションが実行されることを期待しているため、多くの人をつまずかせます(そしてアクティブなルートでバブリングします)。これをさらに悪化させるのは、エラーメッセージがログに記録されないことです。親コンポーネントはエラーを飲み込むだけです。

原則として、アクションは現在のコンテキストで実行されます。非コンポーネントテンプレートの場合、そのコンテキストは現在のコントローラーですが、コンポーネントテンプレートの場合は、親コンポーネント(存在する場合)、またはコンポーネントがネストされていない場合は現在のコントローラーです。

したがって、上記の場合、band-listコンポーネントは、band-list-itemから受け取ったアクションを再起動する必要があります。それをコントローラーまたはルートにバブルアップするため。

// app/components/band-list.js export default Ember.Component.extend({ bands: [], favoriteAction: 'setFavoriteBand', actions: { setAsFavorite: function(band) { this.sendAction('favoriteAction', band); } } });

band-listの場合bandsで定義されましたテンプレート、次にsetFavoriteBandアクションはbandsで処理する必要がありますコントローラまたはbandsルート(またはその親ルートの1つ)。

エンバーの緩和計画

ネストのレベルが多い場合(たとえば、fav-button内にband-list-itemコンポーネントがある場合)、これはより複雑になることが想像できます。メッセージを出すには、内側からいくつかのレイヤーに穴を開け、各レベルで意味のある名前を定義する必要があります(setAsFavorite、favoriteAction、faveActionなど)。

s corp c corp llc

これは、 「改善されたアクションRFC」 、これはすでにマスターブランチで利用可能であり、おそらく1.13に含まれる予定です。

上記の例は、次のように簡略化されます。

// app/templates/components/band-list.hbs {#each bands as } {{band-list-item band=band setFavBand=(action 'setFavoriteBand')}} {{/each}} // app/templates/components/band-list-item.hbs {{band.name}} Fave this

よくある間違いその6:依存キーとして配列プロパティを使用する

Emberの計算されたプロパティは他のプロパティに依存しており、この依存関係は開発者が明示的に定義する必要があります。 isAdminがあるとしましょうロールの1つがadminである場合にのみ真である必要があるプロパティ。これは人がそれを書くかもしれない方法です:

isAdmin: function() { return this.get('roles').contains('admin'); }.property('roles')

上記の定義では、isAdminの値rolesの場合にのみ無効になります配列オブジェクト自体は変更されますが、アイテムが既存の配列に追加または削除された場合は変更されません。追加と削除も再計算をトリガーする必要があることを定義する特別な構文があります。

isAdmin: function() { return this.get('roles').contains('admin'); }.property('roles.[]')

よくある間違いその7:オブザーバーに優しい方法を使用していない

Common Mistake No. 6の(現在修正されている)例を拡張して、アプリケーションでUserクラスを作成しましょう。

var User = Ember.Object.extend({ initRoles: function() { var roles = this.get('roles'); if (!roles) { this.set('roles', []); } }.on('init'), isAdmin: function() { return this.get('roles').contains('admin'); }.property('roles.[]') });

adminを追加するとそのようなUserの役割、私たちは驚きに満ちています:

var user = User.create(); user.get('isAdmin'); // => false user.get('roles').push('admin'); user.get('isAdmin'); // => false ?

問題は、ストックJavascriptメソッドが使用されている場合、オブザーバーが起動しない(したがって、計算されたプロパティが更新されない)ことです。これは、 Object.observe ブラウザでは改善されますが、それまでは、Emberが提供する一連のメソッドを使用する必要があります。現在の場合、pushObject pushと同等のオブザーバーフレンドリーです。

user.get('roles').pushObject('admin'); user.get('isAdmin'); // => true, finally!

よくある間違いその8:コンポーネントのプロパティで渡される突然変異

star-ratingがあると想像してくださいアイテムの評価を表示し、アイテムの評価を設定できるコンポーネント。評価は、歌、本、またはサッカー選手のドリブルスキルに対して行うことができます。

テンプレートでは次のように使用します。

{song} {{star-rating item=song rating=song.rating}} {{/each}}

さらに、コンポーネントが星を表示し、各ポイントに1つの完全な星が表示され、その後、最大評価まで空の星が表示されると仮定します。星がクリックされると、setアクションはコントローラーで実行され、ユーザーが評価を更新したいと解釈する必要があります。これを実現するために、次のコードを書くことができます。

// app/components/star-rating.js export default Ember.Component.extend({ item: null, rating: 0, (...) actions: { set: function(newRating) { var item = this.get('item'); item.set('rating', newRating); return item.save(); } } });

それで仕事は終わりますが、いくつか問題があります。まず、渡されたアイテムにratingがあることを前提としています。プロパティであるため、このコンポーネントを使用してLeo Messiのドリブルスキルを管理することはできません(このプロパティはscoreと呼ばれる場合があります)。

次に、コンポーネント内のアイテムの評価を変更します。これは、特定のプロパティが変更される理由を理解するのが難しいシナリオにつながります。同じテンプレートに別のコンポーネントがあり、その評価も使用されているとします。たとえば、サッカー選手の平均スコアを計算するために使用されます。

このシナリオの複雑さを軽減するためのスローガンは、「データダウン、アクションアップ」(DDAU)です。データは(ルートからコントローラー、コンポーネントに)渡される必要がありますが、コンポーネントはアクションを使用して、これらのデータの変更についてコンテキストに通知する必要があります。では、ここでDDAUをどのように適用する必要がありますか?

評価を更新するために送信する必要のあるアクション名を追加しましょう。

{song} {{star-rating item=song rating=song.rating setAction='updateRating'}} {{/each}}

次に、その名前を使用してアクションを送信します。

コンサルティングビジネスのためのクライアントを取得する方法
// app/components/star-rating.js export default Ember.Component.extend({ item: null, rating: 0, (...) actions: { set: function(newRating) { var item = this.get('item'); this.sendAction('setAction', { item: this.get('item'), rating: newRating }); } } });

最後に、アクションはコントローラーまたはルートによってアップストリームで処理されます。ここで、アイテムの評価が更新されます。

// app/routes/player.js export default Ember.Route.extend({ actions: { updateRating: function(params) { var skill = params.item, rating = params.rating; skill.set('score', rating); return skill.save(); } } });

これが発生すると、この変更はstar-ratingに渡されたバインディングを介して下方に伝播されます。その結果、表示される星の数が変化します。

このように、コンポーネントでミューテーションが発生することはなく、アプリ固有の部分はルート内のアクションの処理のみであるため、コンポーネントの再利用性が損なわれることはありません。

サッカーのスキルにも同じコンポーネントを使用できます。

{skill} {{star-rating item=skill rating=skill.score setAction='updateSkill'}} {{/each}}

最後の言葉

ここで書いたものを含め、人々が犯した(または自分自身を犯した)間違いのいくつか(ほとんど?)は、2.xシリーズの早い段階で消えるか大幅に軽減されることに注意することが重要です。 Ember.jsの。

残っていることは上記の私の提案で対処されているので、Ember 2.xで開発すると、それ以上エラーを起こす言い訳はできなくなります。この記事をPDFとしてご希望の場合は、 私のブログに行きなさい 投稿の下部にあるリンクをクリックします。

私について

私はフロントエンドの世界に来ました Ember.js 2年前、私はここに滞在しています。私はEmberに非常に熱心になり、ゲストの投稿と自分のブログの両方で熱心にブログを書き始め、会議で発表しました。私も本を書きました、 Ember.jsでロックンロール 、Emberを学びたい人のために。サンプルチャプターをダウンロードできます ここに 。

Webフォームの終わり

Uxデザイン

Webフォームの終わり
高度なPowerPointプレゼンテーションのヒントとハック

高度なPowerPointプレゼンテーションのヒントとハック

財務プロセス

人気の投稿
新しいWeb注文:コンテンツファーストデザインの概要
新しいWeb注文:コンテンツファーストデザインの概要
究極のENSとĐAppチュートリアル
究極のENSとĐAppチュートリアル
マイクロサービス入門:Dropwizardチュートリアル
マイクロサービス入門:Dropwizardチュートリアル
書体分類のニュアンスを理解する
書体分類のニュアンスを理解する
FlutterとAngularDartでのコード共有にBLoCを活用する方法
FlutterとAngularDartでのコード共有にBLoCを活用する方法
 
Sass Mixins:スタイルシートを乾いた状態に保つ
Sass Mixins:スタイルシートを乾いた状態に保つ
「ハートブリード」OpenSSLバグの修正:システム管理者向けのチュートリアル
「ハートブリード」OpenSSLバグの修正:システム管理者向けのチュートリアル
タイムロックウォレット:イーサリアムスマートコントラクトの概要
タイムロックウォレット:イーサリアムスマートコントラクトの概要
プロスポーツフランチャイズ評価
プロスポーツフランチャイズ評価
開発者向けの設計ワークフローチュートリアル:より優れたUI / UXを時間どおりに提供
開発者向けの設計ワークフローチュートリアル:より優れたUI / UXを時間どおりに提供
人気の投稿
  • ノードjsフルスタックフレームワーク
  • 購入者の力を減らす2つの方法は、コストとロイヤルティプログラムを切り替えることです。
  • ノードjsが使用される理由
  • グーグル自然言語APIの例
  • 最高財務責任者の役割は何ですか
  • node.jsは習得が難しい
カテゴリー
仕事の未来 データサイエンスとデータベース 分散チーム 製品ライフサイクル Webフロントエンド 人とチーム 技術 アジャイルタレント Uxデザイン その他

© 2021 | 全著作権所有

apeescape2.com