
ある曇りの朝、古いプロジェクトの1つを適切にリファクタリングするといいと思いました。 これは、1つの3DシューティングゲームでHUDをカスタマイズするための非営利の軽量アプリケーションです。 私は2年前にそれを書いたが、暑くて経験が浅かった。 その結果、優れたスパゲッティコードの束は、すべての欠点にもかかわらず、その仕事をしていた。 より賢く、より経験豊富になったので、アプリケーションを完全に書き直し、新しいアーキテクチャを与え、サポートと更新を簡素化することにしました。 どうやってやるの? 答えは簡単に思えました-MVCを使用し、レベルに分割し、すべてを1つの全体に接続します。 そのため、強固な基盤となるシンプルで効果的なフレームワークを選択するという問題に直面しました。 簡単な調査の後、
backbone.jsを選択しました。 そのシンプルさと柔軟性が大好き。 ソースを開いて、すべてがどのように機能し、どのように機能するかを理解できます。 喜ばなかった唯一のニュアンスは、MVパターンです。 多数のビューでロジックを塗りつぶしたくなかったので、パズルの欠けている部分を提供する独自の自転車を書くというアイデアが生まれました。 さらに、新しいものを作成することは常に楽しくて興味深いです。 考え直すことなく、バックボーン用のコントローラーの実装に取りかかりました。
問題のステートメントと基本的な方法の実装
そのため、アプリケーションのすべての部分を1つの全体に統合するコントローラーを作成する機能が必要です。 各コントローラーは、すべてのモデルとコレクション(基本的なデザイナーと既に作成されたインスタンスの両方)にアクセスできる必要があります。 また、コンポーネント(ビュー)を作成し、適切に応答するためにイベントをリッスンできる機能も必要です。
コントローラのスケルトンは次のようになります。
Controller = { views: {},
これまでのところ、すべてが非常に簡単です。 しかし、複雑なアプリケーションの場合、複数のコントローラーが必要です。コレクションとモデルのセットは、アプリケーション全体に共通であることが望ましいです。
Application
は私たちの助けになります-コントローラを単一のアプリケーションに結合する基本的なコンストラクターです。
アプリケーションのスケルトンは次のようになります。
Application = {
アプリケーションの起動時に、すべてのコレクションのインスタンスを即座に作成することも役立ちます。 また、アプリケーションの起動後に各コントローラーでコールバック関数を呼び出すと便利です。 このコールバックは、すべての予備データが準備できたときに呼び出す必要があります。 したがって、各コントローラーは、アプリケーションが動作する準備ができていることを「認識」します。 ためらうことなく、メソッドを追加します。
互いに通信するようにコントローラーに教えるだけです。 この目的のために、アプリケーションのすべてのコンポーネント間で通信を確立できるようにする別のエンティティを作成します。
EventBus = {
基本オブジェクトが定義されたので、アプリケーションのすべての部分の具体的な実装を進めることができます。
アプリケーションの実装
メインコンストラクター-Applicationから始めましょう。 バックボーンと同じ方法で基本クラスを実装します。
var Application = function(options) { _.extend(this, options || {});
さらに、
_.extend
.extendを使用して、プロトタイプを拡張します。
_.extend(Application.prototype, {
コントローラーを初期化するには、2つのメソッドが必要です。
Application.initializeControllers
は、コレクションおよびモデルのコレクションをインスタンス化および減算して、アプリケーション自体にリンクを直接格納します。 そして、
Application.launchControllers
は、すでに作成されたコントローラーを通過し、
Controller.onLaunch
コールバックを実行します。
_.extend(Application.prototype, { ... initializeControllers: function(controllers) { this.controllers = {}; _.each(controllers, function(ctrl) { var classReference = resolveNamespace(ctrl), id = ctrl.split('.').pop();
コントローラー間の通信を確保し、特定のコンポーネントからのイベントをサブスクライブできるようにするために、
Application.addListeners
メソッドを追加し
Application.addListeners
メソッドは、作業をEventBusに委任します。
_.extend(Application.prototype, { ... addListeners: function(listeners, controller) { this.eventbus.addListeners(listeners, controller) } ... });
モデルとコレクションを操作するには、インスタンスへの参照、コンストラクターへの参照、および新しいエンティティを作成するメソッドを取得する関数が必要です。 例としてモデルを使用した特定の実装を検討してください;コレクションの場合、関数は同様に機能します。
_.extend(Application.prototype, { ... getModel: function(name) { this._modelsCache = this._modelsCache || {}; var model = this._modelsCache[name], modelClass = this.getModelConstructor(name); if(!model && modelClass) { model = this.createModel(name); this._modelsCache[name] = model; } return model || null; }, getModelConstructor: function(name) { return this.models[name]; }, createModel: function(name, options) { var modelClass = this.getModelConstructor(name), options = _.extend(options || {}); var model = new modelClass(options); return model; }, getCollection: function(name) { ... }, getCollectionConstructor: function(name) { ... }, createCollection: function(name, options) { ... }, ... });
これで、アプリケーションの基本的なコンストラクタの準備が整いました。
Application.parseClasses
メソッドについて言及する必要があり
Application.parseClasses
。 実際、コントローラー、モデル、コレクション、およびビューのリストをストリングの配列として転送することにしました。 入り口に着く
[ 'myApplication.controller.UserManager', 'myApplication.controller.FormBuilder' ]
Application.parseClasses関数は、この配列をマッピングに変換します
{ 'UserManager': myApplication.controller.UserManager, 'FormBuilder': myApplication.controller.FormBuilder }
そこで、2つの問題を解決します。 まず、すべてのリンクは、コンストラクターの名前と同じ一意の識別子に自動的に関連付けられます。 これにより、開発者は個々のエンティティの名前を気にする必要がなくなります。 次に、ベースパーツが使用可能になるのを待たずに、ベースパーツを決定できます。 これにより、ファイルをランダムな順序でアップロードできます。 リンクへの名前の解析は、すべてのスクリプトがロードされた後にのみ行われます。
コントローラーの実装
コントローラーは少し単純なコードを取得するため、モデルとコレクションのすべての作業を
Application
委任し
Application
。 開始するには、発表:
var Controller = function(options) { _.extend(this, options || {}); this.initialize.apply(this, arguments); };
そして、プロトタイプを拡張できます
_.extend(Controller.prototype, { views: {}, models: {}, collections: {}, initialize: function(options) { }, addListeners: function(listeners) { this.getApplication().addListeners(listeners, this); }, onLaunch: function(application) { }, getApplication: function() { return this.application; } });
ビューを操作するメソッドを追加します。
_.extend(Controller.prototype, { ... getViewConstructor: function(name) { return this.views[name]; }, createView: function(name, options) { var view = this.getViewConstructor(name), options = _.extend(options || {}, { alias: name }); return new view(options); } ... });
モデルとコレクションの作業を
Application
委任し
Application
_.extend(Controller.prototype, { ... getModel: function(name) { return this.application.getModel(name); }, getModelConstructor: function(name) { return this.application.getModelConstructor(name); }, createModel: function(name, options) { return this.application.createModel(name) }, getCollection: function(name) { return this.application.getCollection(name); }, getCollectionConstructor: function(name) { return this.application.getCollectionConstructor(name); }, createCollection: function(name, options) { return this.application.createCollection(name); } ... });
そして最後に、コントローラーが
Application.EventBus
を使用して通信できるようにし
Application.EventBus
_.extend(Controller.prototype, { ... fireEvent: function(selector, event, args) { this.application.eventbus.fireEvent(selector, event, args); } ... });
コントローラーの基本的なコンストラクターの準備ができました! 少しだけ残った:)
EventBusの実装
まず、コンストラクターについて説明します。 コントローラがビューからイベントをリッスンできるようにするには、
Backbone.View
基本プロトタイプをわずかに拡張する必要があります。 実際には、イベントを追跡する特定のセレクタが必要です。 これを行うために、コンポーネントの作成時に自動的に割り当てられる
alias
プロパティを導入します。 そして、ネイティブの
View.trigger()
を呼び出し、新しいイベントを
EventBus
に
EventBus
する
fireEvent
メソッドを追加します。
var EventBus = function(options) { var me = this; _.extend(this, options || {});
これで、プロトタイプを安全に拡張できます。
EventBus.addListeners
を使用して新しいイベントをサブスクライブし、
EventBus.fireEvent
が目的のハンドラーを配置して実行します。
_.extend(EventBus.prototype, {
やった! これで、すべての主要部分が実装されました! 最後のタッチ
Application.extend = Backbone.Model.extend; Controller.extend = Backbone.Model.extend;
これで、
extend
関数を使用して、ベースコンストラクターから継承を作成できます。
ドキュメントと例
公式の
Backbone.Applicationページの
ソースファイルと
ドキュメントまた、簡単な
例を作成しました-これはMVCを使用した古典的なToDoです。 実装のソースとコメントはここにあります
-github.com/namad/Backbone.Application/blob/master/examples/ToDo/js/todos.jsボーナスとして、この自転車全体を書いたより複雑な例は、お気に入りのQuake LiveゲームのHUDエディターである
visualHUDです。 現時点では、新しいバージョンはまだ開発中です。多くの小さなことを終える必要がありますが、一般に、すべての機能が動作し、自分の手でそれに触れることができます。
Googleコードの古いバージョンのソース
コードPSこれは、この性質の私の最初の記事であり、何が起こったのか分かりません:)それで、適切なレビューは金の重さの価値があります。 よろしくお願いします!