Backbone JS SPA(シングルページアプリケーション)の基礎的な作業を始めたところです。基本的なアンダースコアテンプレートサポートを使用していますが、予期しないルーティングが発生するという問題があります。
基本的に、サインアップビューは最初は期待どおりに表示され、ボタンをクリックして単純なテストビューに移動するとPOSTが正常に表示されます。ただし、テストビューはすぐにレンダリングされ、デフォルトのサインアップビューに再度ルーティングされます。
テストページの履歴が表示され、戻るボタンを押すと、正常に機能するテストビューに戻ります。バックボーンでトリガーされ、空白のフラグメント(サインアップページ)に戻るイベントが発生しているようですが、理由はわかりません。運が悪かったので、ナビゲート呼び出しの置換オプションとトリガーオプションをいじってみました。
補足として、start()およびstop()ビュー関数はこの記事から採用されました:http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone -apps/。これを削除してみましたが、効果がありませんでした。
$(document).ready( function(){
Backbone.View.prototype.start = function() {
console.debug('starting');
if (this.model && this.modelEvents) {
_.each(this.modelEvents,
function(functionName, event) {
this.model.bind(event, this[functionName], this);
}, this);
}
console.debug('started');
return this;
};
Backbone.View.prototype.stop = function() {
console.debug('stopping');
if (this.model && this.modelEvents) {
_.each(this.modelEvents,
function(functionName, event) {
this.model.unbind(event, this[functionName]);
}, this);
}
console.debug('stopped');
return this;
};
var myApp = {};
myApp.SignUp = Backbone.Model.extend({
urlRoot:"rest/v1/user",
defaults: {
emailAddress: "email@me.com",
firstName: "First Name",
lastName: "Last Name",
password: "",
confirmPassword: ""
}
});
myApp.SignUpView = Backbone.View.extend({
el: $('#bodyTarget'),
modelEvents: {
'change' : 'render'
},
render: function(){
document.title = "Sign Up Page";
// Compile the template using underscore
var template = _.template( $("#signUpTemplate").html(), this.model.toJSON());
// Load the compiled HTML into the Backbone "el"
this.$el.html( template );
return this;
},
events: {
"click .signUpButton": "signUp"
},
signUp: function() {
bindFormValues(this);
this.model.save(this.model.attributes, {error: this.signUpFailure});
myApp.router.navigate("test", {trigger: true});
},
signUpFailure: function(model, response) {
alert("Failure: " + response);
}
});
myApp.TestView = Backbone.View.extend({
el: $('#bodyTarget'),
modelEvents: {
'change' : 'render'
},
render: function() {
document.title = "Test Page";
this.$el.html( "<div>this is a test view</div>");
return this;
}
});
// for now, just pull values from form back into model
function bindFormValues(view) {
var mod = view.model;
var el = view.$el;
var updates = {};
for (var prop in mod.attributes) {
var found = el.find('* [name="' + prop + '"]');
if (found.length > 0) {
updates[prop] = found.val();
}
}
mod.set(updates/*, {error: errorHandler}*/);
}
// routers
myApp.Router = Backbone.Router.extend({
routes: {
'test': 'test',
'': 'home',
},
home: function() {
console.debug('home:enter');
this.signUpView = new myApp.SignUpView({model: new myApp.SignUp()});
this.showView(this.signUpView);
console.debug('home:exit');
},
test: function() {
console.debug('test:enter');
this.testView = new myApp.TestView({model: new myApp.SignUp()});
this.showView(this.testView);
console.debug('test:exit');
},
showView: function(view) {
if (this.currentView) {
this.currentView.stop();
}
this.currentView = view.start().render();
}
});
myApp.router = new myApp.Router();
Backbone.history.start();
});
私のHTMLページは、関連するスクリプトを取り込むだけで、ロード時にビューが挿入されるdiv要素bodyTargetがあります。
編集:ええと、私は問題を見つけました。falseを返すことにより、signUp()の呼び出しでイベントが伝播しないようにする必要があることがわかりました。