私はビューとルーターをrequireで別々のファイルに分けています。次に、ルーターをインスタンス化し、デフォルトビューをレンダリングするmain.jsファイルを作成します。
ルーターには、ルートとしてビュー( 'View /:id')および編集( 'Edit /:id')があります。 main.jsでは、ルーターをインスタンス化するときにrouter.navigate( 'View/1'、true)をハードコーディングでき、ナビゲーションは正常に機能します。ビューファイルで、編集リンクをクリックすると、router.navigate( 'View /' + id、true)を呼び出したいのですが、どうすればいいのかわかりません。
Backbone.history.navigate( 'View /' + id、true)の呼び出しに成功しましたが、グローバルBackboneオブジェクトに依存する必要があるとは思いません。
This.options.router.navigate()を使用できるように({router:appRouter})をビューに渡そうとしましたが、それはうまくいきませんでした。
好奇心が強い場合のために、ここに私のアプリからのコードの束があります:
ルーター:
define(['./View', './Edit'], function (View, Edit) {
return Backbone.Router.extend({
routes: {
'View/:id': 'view',
'Edit/:id': 'edit'
},
view: function (id) {
var model = this.collection.get(id);
var view = new View({ model: model });
view.render();
},
edit: function (id) {
var model = this.collection.get(id);
var edit = new Edit({ model: model });
edit.render();
}
});
});
見る:
define(function () {
return Backbone.View.extend({
template: Handlebars.compile($('#template').html()),
events: {
'click .edit': 'edit'
},
render: function () {
//Create and insert the cover letter view
$(this.el).html(this.template(this.model.toJSON()));
$('#View').html(this.el);
return this;
},
edit: function () {
Backbone.history.navigate('Edit/' + this.model.id, true);
},
});
});
ほとんどのバックボーンの質問と同様に、これを処理する方法はたくさんあります。現在のプロジェクトで私がアプローチした方法は、すべてをグローバルなカスタム名前空間に配置し、それを使用して必要な参照を渡すことでした。
_var MyNamespace = {};
MyNamespace.init = function() {
MyNamespace.appView = new MyAppView();
MyNamespace.router = new MyRouter();
// etc
}
_
ビューは、必要に応じて_MyNamespace.router
_を参照できます。しかし、これはrequire.jsでは機能しない/推奨されていないようですので、他のオプションをいくつか示します:
ルーターを明示的に呼び出さないでください。代わりに、ルーターがリッスンするグローバル状態オブジェクトを変更してください。これが実際に現在のプロジェクトで私がやったことです-詳細は this response をご覧ください。
ルーターをトップレベルのビュー(多くの場合AppView
と呼ばれる)に接続し、グローバルにアクセスできるようにし、AppView.router.navigate()
を使用します。
内部でBackbone.history.navigate()
を呼び出すnavigate
ユーティリティ関数を提供する別のモジュールを作成します。これはあなたがやっていることと大した違いはありませんが、少しモジュール化され、常にグローバル参照を使用することを防ぎます。これにより、内部実装を変更することもできます。
私のように他の誰かがこの問題の解決策を探している場合、私がやったことを投稿しています。ボイラープレートのbackbone.jsを使用している場合、_router.js
_にinitialize()
関数があります。 initialize()
関数を次のように変更しました。
_initialize = function () {
var app_router;
app_router = new AppRouter();
// Extend the View class to include a navigation method goTo
Backbone.View.goTo = function (loc) {
app_router.navigate(loc, true);
};
Backbone.history.start();
};
_
Backbone.jsの継承の特定のフレーバーにより、これにより、任意のビュー内からMyView.goTo(location);
を呼び出すことができます。
Window.location.hashを使用して、昔ながらの方法でそれを行うことができます:)
window.location.hash = "Edit/1"
明示的なルートが必要ない場合の代替ソリューションを次に示します。アプリの起動時に、Backbone Eventsを拡張するオブジェクトを作成します
window.EventDispatcher = _.extend({}, Backbone.Events);
その後、アプリのどこでもイベントをリッスンできます
EventDispatcher.bind("mymodel:edit", this.editHandler, this);
また、どこからでもイベントをディスパッチします。以下のdata
は、ライドのために送信したいパラメータです。
EventDispatcher.trigger("mymodel:edit", data);
私にとっては、goTo関数を使用したソリューションはわずかな変更で機能しました
Backbone.View.prototype.goTo = function (loc) {
appRouter.navigate(loc, true);
};
私はこの質問が古いことを知っていますが、なぜルーターを取得するためにrequire.jsを使用しないのか疑問に思っています:
define(['./PathToRouter', ], function (router) {
return Backbone.View.extend({
template: Handlebars.compile($('#template').html()),
events: {
'click .edit': 'edit'
},
render: function () {
//Create and insert the cover letter view
$(this.el).html(this.template(this.model.toJSON()));
$('#View').html(this.el);
return this;
},
edit: function () {
router.navigate('Edit/' + this.model.id, true);
}
});
});
このアプローチはどうですか?バックボーンはその4つのコンポーネントすべてにテンプレートパターンを実装しているため、少しのデザインで、循環参照を行うことなくアプリのルーターを介して各ビューに簡単なナビゲーションメカニズムを提供できます(これは他の同様の投稿で見たものですが、それを避けるようにしてください)。
ルーターコンポーネント、他のルーターの例とそれほど変わらない:
define('Router', ['backbone', ... ],
function (Backbone, ...) {
var MyRouter = Backbone.Router.extend({
routes: {
'viewA': 'viewA',
'viewB': 'viewB'
},
initialize: function () {
...
};
},
viewA: function () {
...
},
viewB: function () {
...
}
});
return MyRouter;
});
アプリは、ルーターインスタンスを作成し、このインスタンスを渡す最初のビューを起動します。
define('App', ['backbone', ...
], function (Backbone, ...) {
function initialize() {
//route creation
if (!this.routes)
routes = new Router(this);
//backbone history start
Backbone.history.start();
//ViewA navigation, bigbang
if (!this.viewA)
this.viewA = new ViewA({router: this.routes});
this.viewA.render();
}
return {
initialize: initialize
};
});
BaseView、すべてのビューの基本コンストラクター定義、およびナビゲーションメソッド:
define('BaseView', ['jquery', 'underscore', 'backbone', ...
], function ($, _, Backbone, ...) {
var BaseView;
BaseView = Backbone.View.extend({
id: '...',
constructor: function (options) {
this.router = options.router;
this.model = options.model;
Backbone.View.prototype.constructor.call(this);
},
initialize: function () {
this.template = _.template(tpl);
},
events: {
},
render: function () {
$(this.el).html(this.template());
return this;
},
//Provides transparent navigation between views throught the backbonejs
//route mechanism
navigate: function(pageId)
{
this.router.navigate(pageId, {trigger: true});
}
});
return BaseView;
});
Viewインスタンス。各ビューはバックボーンではなくベースビューから拡張し、ベースの動作を継承します。
define('ViewA', ['jquery', 'underscore', 'backbone', 'BaseView'
], function ($, _, Backbone, BaseView) {
var ViewA;
ViewA = BaseView.extend({
id: '...',
constructor: function (options) {
this._super("constructor");
},
...
foo: function()
{
...
this.navigate("viewB");
}
});
return ViewA;
});
それは私のために機能し、また他のプロジェクトで再利用することもできます。
私にとっては、メインアプリケーションにオブジェクトを追加しました。
define(['jquery','underscore','backbone','views/personView','views/peopleView','views/textView'],function($,_,backbone,PersonView,PeopleView,TitleView){
var Router = Backbone.Router.extend({
routes:{
'':'home',
'edit/:id':'editPerson',
'new':'editPerson',
'delete/:id':'deletePerson'
}
})
var initialize = function(){
var router = new Router();
window.app = {
router:router
}
router.on('route:home',function(){
})
//enable routing using '#'[hashtag] navigation
Backbone.history.start();
};
return {
initialize:initialize
};
});
ビュー内でwindows.app.router.navigate({''、trigger:true})と言うことができます。この場合、グローバルスコープが適切なプラクティスであるかどうかはわかりませんが、私にとってはうまくいきました。
AMDモジュールをルーティングするための新しいソリューションがあります。
RequireJSルーター https://github.com/erikringsmuth/requirejs-router
これは、各ページに移動するときにAMDモジュールを遅延ロードするアプローチを取ります。 Backboneルーターでは、すべてのビューを事前に依存関係として要求する必要があります。これにより、最初のページの読み込み時にすべてのアプリのJavascriptが読み込まれます。 RequireJSルーターは、各ルートに移動するとモジュールを遅延ロードします。
アプリの実行に使用されるmain.jsの例
define([], function() {
'use strict';
// Configure require.js paths and shims
require.config({
paths: {
'text': 'bower_components/requirejs-text/text',
'router': 'bower_components/requirejs-router/router'
}
});
// Load the router and your layout
require(['router', 'js/layout/layoutView'], function(router, LayoutView) {
var layoutView = new LayoutView();
// The layout's render method should draw the header, footer, and an empty main-content section
// then load the content section.
// render: function() {
// this.$el.html(this.template({model: this.model}));
// router.loadCurrentRoute();
// }
// Configure the router
router
.registerRoutes({
home: {path: '/', moduleId: 'home/homeView'},
order: {path: '/order', moduleId: 'order/orderView'},
notFound: {path: '*', moduleId: 'notFound/notFoundView'}
})
.on('statechange', function() {
// Render the layout before loading the current route's module
layoutView.render.call(layoutView);
})
.on('routeload', function(module, routeArguments) {
// Attach the content view to the layoutView's main-content section
layoutView.$('#main-content').replaceWith(new module(routeArguments).render().el);
})
.init({
// We're manually calling loadCurrentRoute() from layoutView.render()
loadCurrentRouteOnStateChange: false
});
);
);