前回のチュートリアルでは、Discourse がリクエストに応答するようにサーバー側とクライアント側の両方を設定する方法を説明しました。
ここでは、Ember コンポーネントのドキュメントを読むことをお勧めします。Introducing Components - Components - Ember Guides
古いチュートリアル
このチュートリアルでは、サードパーティの JavaScript をラップする方法として、新しい Ember コンポーネント を作成します。これは、以前私が作成した YouTube の動画と似ており、参考になるかもしれませんが、今回は Discourse に特化し、プロジェクト内のファイルの配置方法に焦点を当てます。
なぜコンポーネントなのか?
Handlebars は非常にシンプルなテンプレート言語です。動的な部分を持つ通常の HTML にすぎません。学習は簡単で生産性も向上しますが、コードの再利用にはあまり適していません。Discourse のような大規模なアプリケーションを開発していると、同じものを何度も再利用したいと思うようになるでしょう。
コンポーネントは、この問題に対する Ember の解決策です。スナックをより見栄え良く表示するコンポーネントを作成してみましょう。
新しいコンポーネントの作成
コンポーネントの名前にはダッシュを含める必要があります。今回は fancy-snack という名前を選択します。テンプレートを作成しましょう。
app/assets/javascripts/admin/templates/components/fancy-snack.hbs
<div class="fancy-snack-title">
<h1>{{snack.name}}</h1>
</div>
<div class="fancy-snack-description">
<p>{{snack.description}}</p>
</div>
次に、コンポーネントを使用するために、既存の admin/snack テンプレートを次のように置き換えます。
app/assets/javascripts/admin/templates/snack.hbs
{{fancy-snack snack=model}}
これで、必要なモデルを渡すだけで、他のどのテンプレートでも fancy-snack コンポーネントを再利用できるようになりました。
カスタム JavaScript コードの追加
再利用性に加えて、Ember のコンポーネントは、カスタム JavaScript、jQuery、その他の外部コードを安全に追加するのに優れています。コンポーネントがページに挿入されるタイミングと、削除されるタイミングを制御できます。これを行うには、いくつかのコードを持つ Ember.Component を定義します。
app/assets/javascripts/admin/components/fancy-snack.js
export default Ember.Component.extend({
didInsertElement() {
this._super();
this.$().animate({ backgroundColor: "yellow" }, 2000);
},
willDestroyElement() {
this._super();
this.$().stop();
},
});
上記のコードを追加してページを更新すると、スナックの背景がゆっくりと黄色にフェードするアニメーションが表示されることがわかります。
ここで何が起こっているのかを説明します。
-
コンポーネントがページにレンダリングされると、
didInsertElementが呼び出されます。 -
didInsertElement(およびwillDestroyElement) の最初の行はthis._super()であり、これは Ember.Component をサブクラス化 しているため必要です。 -
アニメーションは jQuery の animate 関数を使用して実行されます。
-
最後に、アニメーションはコンポーネントがページから削除されたときに呼び出される
willDestroyElementフックでキャンセルされます。
willDestroyElement について気にする理由があるのか疑問に思うかもしれません。その理由は、Discourse のような長期間稼働する JavaScript アプリケーションでは、メモリリークや実行中のまま残ることを避けるために、後始末をすることが重要だからです。この場合、アニメーションを停止することで、コンポーネントがもはやページに表示されていないため、jQuery のタイマーがこれ以上発火しないように指示します。
次のステップ
このシリーズの最終チュートリアルでは、自動テストについて説明します。
このドキュメントはバージョン管理されています - 変更の提案は github で行えます。