現在、backbone.jsで構築された大規模なWebアプリに取り組んでおり、組織、「ゾンビ」などで多くの問題を抱えているため、コードの主要なリファクタリングを行うことにしました。 「ゾンビ」に対処するためのヘルパー関数をすでに書いています。ただし、最初から始めて、コードにNice構造/組織を作成したいと思います。大規模なbackbone.jsの組織に関する素晴らしいチュートリアル/例があまりないので、ゼロから始めたので、始めたところについて意見を得ることができるかどうかを確認したいと思います。
私は明らかにグローバルな名前空間内にコードをセットアップしました。しかし、私はその名前空間をかなりきれいに保ちたいです。私のメインのapp.jsは、クラスファイル自体をグローバルネームスペースから分離しています。 reg()関数を使用して(インスタンス化できるように)クラスを登録し、inst()関数がクラス配列からクラスをインスタンス化できます。したがって、3つのメソッドに加えて、MyApp名前空間にはRouter、Model、Viewのみがあります。
var MyApp = (function () {
var classes = {
Routers: {},
Collections: {},
Models: {},
Views: {}
};
methods = {
init: function () {
MyApp.Router = MyApp.inst('Routers', 'App');
MyApp.Model = MyApp.inst('Models', 'App');
MyApp.View = MyApp.inst('Views', 'App');
Backbone.history.start();
},
reg: function (type, name, C) {
classes[type][name] = C;
},
inst: function (type, C, attrs) {
return new classes[type][C](attrs || {});
}
};
return methods;
}());
$(MyApp.init);
Models、Collections、Routers、Views内で、私はいつものように作業しますが、ファイルの最後にそのクラスを登録して、後で名前空間を乱雑にすることなくインスタンス化できるようにする必要があります:
MyApp.reg('Models', 'App', Model);
これはコードを整理するための不必要な方法のように思えますか?他の人は、多くのルーター、コレクション、モデル、ビューを備えた本当に大きなプロジェクトを整理する方法のより良い例を持っていますか?
私は最近、GapVis( コードはこちら 、 レンダリングされたコンテンツはこちら )と呼ばれるBackboneプロジェクトに取り組みました。 「本当に大きい」かどうかはわかりませんが、大きくて比較的複雑です-24のビュークラス、5つのルーターなど。すべてのアプローチがそうなることはわかりませんが、見てみる価値はあります。関連する。 メインapp.jsファイル の長いイントロコメントで私の考えの一部を見ることができます。いくつかの重要なアーキテクチャの選択:
すべての現在の状態情報を保持するシングルトンState
モデルがあります-現在のビュー、現在見ているモデルIDなど。アプリケーションの状態を変更する必要があるすべてのビューは、State
、および状態に応答する必要があるすべてのビューは、イベントのモデルをリッスンします。これは、状態を変更して更新するビューにも当てはまります。events
のUIイベントハンドラーはビューを再レンダリングすることはなく、代わりにレンダリング関数を状態にバインドすることで行われます。このパターンは、ビューを互いに分離するのに役立ちました。ビューは別のビューのメソッドを呼び出すことはありません。
私のルーターは特殊なビューのように扱われます-状態を更新することでUIイベント(つまりURLを入力する)に応答し、UIを更新する(つまりURLを変更する)ことで状態の変化に応答します。
私はあなたが提案していることに似たいくつかのことをします。私の名前空間には、あなたのものに似たinit
関数と、定数用のsettings
オブジェクトがあります。しかし、複数のファイルでそれらを参照する必要があるため、ほとんどのモデルクラスとビュークラスも名前空間に配置しました。
私はルーターに登録システムを使用し、「マスター」クラス(AppRouter
およびAppView
)がすべてのビューを認識しなくて済むようにするための素敵な方法として、ビューに1つを検討しました。 。ただし、AppView
の場合、子ビューの順序が重要であることが判明したため、それらのクラスをハードコーディングしました。
これが物事を行うための「正しい」方法だとはほとんど言いませんが、それは私にとってはうまくいきました。それが役立つことを願っています-また、Backboneを使用して大規模プロジェクトの目に見えるソースの例を見つけるのに苦労しました。
これら2つのリソースは、バックボーンアプリを堅固な基盤にセットアップするのに役立ちました。
実際、さまざまな方法でさまざまな方法の長所と短所があります。最も重要なことは、ファイルを整理する適切な方法を見つけることです。以下は、現在行っているプロジェクトの構成です。この方法では、同じモジュール関連のファイルがフォルダーに配置されることに焦点が置かれます。例:peopleモジュール、このモジュールはすべてのファイルがmodules/base/peopleディレクトリに配置されます。このモジュールの更新とメンテナンスの後、ライン上のこのディレクトリ内のファイルのみに注目する必要があり、ディレクトリ外のファイルには影響を与えず、メンテナンス性が向上します。
私の答えがあなたにいくらかの助けを与えることを願っています、あなたにいくつかの貴重なアドバイスを願っています。
私はあなたがやっていること(少なくともクラスの部分)に似た名前空間を持ち、すべてのモデル、ビュー、コントローラーは次のようになります:
views/blocks.js:
_(function(cn){
cn.classes.views.blocks = cn.classes.views.base.extend({
events: {},
blocksTemplate: cn.helpers.loadTemplate('tmpl_page_blocks'),
initialize: function(){
},
render: function(){
$(this.el).html(this.blocksTemplate());
},
registerEvents: function(){},
unregisterEvents: function(){}
});
})(companyname);
_
私のJavaScript名前空間は次のようになりますが、新しいアプリを作成するたびに改善しています。
_ companyname:{
$: function(){}, <== Shortcut reference to document.getElementById
appView: {}, <== Reference to instantiated AppView class.
classes = { <== Namespace for all custom Backbone classes.
views : {},
models : {},
collections: {},
controllers : {},
Router: null
},
models: {}, <== Instantiated models.
controllers: {}, <== Instantiated controllers.
router: {}, <== Instantiated routers.
helpers: {}, <== Reusable helper platform methods.
currentView: {}, <== A reference to the current view so that we can destroy it.
init: function(){} <== Bootstrap code, starts the app.
}
_
すべてのビューに必要なものはすべて、ベースビューに配置します。私のコントローラーは、(レンダリング後)作成する新しいビューでregisterEvents
を呼び出し、それを強制終了する直前にビューでunregisterEvents
を呼び出します。すべてのビューにこれらの2つの追加メソッドがあるわけではないため、最初に存在を確認します。
すべてのビューにthis.el.remove();
が組み込まれていることを忘れないでください。ビューコンテナ要素を強制終了するだけでなく、それに関連付けられているすべてのイベントのバインドを解除します。コントローラーを介してビューを作成する方法によっては、実際に要素を強制終了し、代わりにthis.el.unbind()を実行してすべてのイベントをアンバインドすることはできません。