この問題については多くの議論がありましたが、その多くは、ルーターが正式にコントローラーと呼ばれていることについての混乱から生じたと思います。去年の終わりにBackboneを使い始めた頃には、すでに変更が加えられていましたが、多くの人がすでにコントローラーであるルーターを中心にアプリケーションを構築していたと思います。私はそれに同意しませんでした。私にとって、Backboneが作成されるずっと前にBackboneと同様の独自のMVCエンジンを構築した経験に依存して、ルーターは単なる履歴マネージャーコンポーネントでした。
したがって、ルーターの実装に最適な方法を決定する際の特定の問題に対処するには、いくつかの点を考慮してください。
- まず第一に、ルーターはアプリケーションの必須コンポーネントではありません。ルーターがなくても、アプリのさまざまなページや画面に移動できます。
- ルーターは、その主な機能が履歴の管理であるという点でコントローラーではありません。アプリケーションのビジネスロジックをルーターに埋め込むことはできますが、それがルーターの実際の機能の水面を濁していることにいつも気づきました。
- ルーターをアプリケーションのコンポーネントにすることで、関心の分離を改善し、はるかに効果的なパブ/サブタイプの配置を実現できます。
以下は、メディエーター、pub / subパターンに従う、アプリで使用するルーターモジュールのコードです。
/**
* The idea behind this component is simply to relegate Backbone.Router to
* doing what it does best: History Management. All it is responsible for
* is two things:
*
* 1. Update the URL if router.navigate is invoked
* 2. Trigger a routeChanged event if the URL was updated either by a bookmark or
* typed in by a user.
*/
define(function () {
return Backbone.Router.extend({
initialize : function (map) {
this._reversedMap = this.reverseModuleMap(map);
},
routes:{
'*actions':'notify'
},
notify:function (actions) {
var args = arguments;
this.trigger("routeChanged", {command:actions});
},
/**
* Override Backbone.Router.navigate. Default is to pass a router fragment, but for
* our uses, we'll translate the "route" into a module mapping so that the controller
* will know which module to display.
* @param param
* @param options
*/
navigate:function (param, options) {
//console.log('navigate', param);
if(!param.suppressNavigate && param.actionCommand) {
Backbone.Router.prototype.navigate.call(this, this._reversedMap[param.actionCommand]);
} else if(!param.actionCommand) {
Backbone.Router.prototype.navigate.call(this, param, options);
}
},
/**
* this function simply reverses the key and value of the "map"
* @param map
*/
reverseModuleMap:function (map) {
var newMap = {};
_.each(map, function (value, key) {
newMap[value] = key;
});
// reversed key and value
return newMap;
}
});
});
次に、コンポーネントをインスタンス化するときに、マップを渡して、コントローラーがナビゲートするモジュールを認識できるようにします。
this._router = new Router({
_default: 'moduleA',
sites : 'moduleA',
apps : 'moduleB'
});
this._router.on('routeChanged', this.handleRouteChange, this);
これで私が見つけた最も重要なことは、コードを素晴らしくシンプルに保ち、コントローラーのビジネスロジックに集中できることです。