この質問に対する正しい答えは実際にはありません。それを機能させる方法は確かに複数あり、それが Backbonejs の優れた点の 1 つです。非常に柔軟であり、多くの設計上の選択を迫られることはありません。
あなたが説明しているものを構築し始めるとしたら、確かに次のようになります。
Question
モデル_
Questions
コレクション_
QuestionView
単一の質問をレンダリングするための
QuestionsIndexView
質問のリストを表示するためのa
それ以降は、少しあいまいになりますが、アプリの要件によって異なります。状態を従来の Web サイトのように保存したい場合は、ルーターを使用して次のようにします。
ApplicationRouter = Backbone.Router.extend({
routes: {
"": "index",
"question/:id": "show"
},
index: function() {
// render a QuestionsIndexView...
},
show: function(id) {
// find the q and render a QuestionView...
}
})
状態が URL で維持されるため、ユーザーはブラウザの [進む] ボタンと [戻る] ボタンを使用でき、期待どおりに動作する可能性があるため、これは便利です。これの問題は、これらnextQuestion
とpreviousQuestion
ボタンをどのように機能させるべきかということです。
それらを質問の一部にする場合QuestionView
、次の質問と前の質問のIDが何であるかを知る必要があります。おそらくこれを機能させるスキームを思い付くことができますが、よりエレガントで頻繁に使用されるパターンは、既に言及したすべてのデータ モデルの上に存在する別のモデルを作成し、このモデルのおよび属性をApp
作成することです。次に、ルーターのメソッドでこの属性を更新します。QuestionsCollection
current_question_id
current_question_id
アプリケーションの状態は、ブラウザの URL に保持されるだけでなく、監視可能なオブジェクトとしてアプリケーション層にも存在します。ButtonsPanelView
このモデルを通過しApp
、ボタンがクリックされたときに正しいルートをトリガーするを簡単に作成できます。また、モデルに and を実装し、それを使用してhasNextQuestion
、ユーザーが前後に移動できないときにそれぞれのボタンを無効にすることも簡単です。hasPreviousQuestion
App
toggle
要求に応じて編集:
App
すべての上に存在するモデルを作成するのは非常に簡単です。おそらく、次のようなコードがすでにどこかにあるでしょう。
window._qs = new Questions();
window._qs.fetch();
代わりにこれを行うだけです:
var qs = new Questions();
window.app = new App({questions: qs});
qs.fetch();
コレクションはQuestions
、私たちが望んでいたように、アプリ モデルの属性になりました。App
では、どのように見えるかの定義は何ですか? 繰り返しますが、これには多くの方法がありますが、Backbone.Models の検証を使用して、悪い状態に陥らないようにするのが好きです。これが私ができることです:
App = Backbone.Model.extend({
defaults: {
current_question_index: 0
},
validate: function(attrs) {
if(typeof attrs.current_question_index !== "undefined") {
// we are trying the change the question index,
// so make sure it is valid
var len = this.get("questions").length
if(attrs.current_question_index < 0 || attrs.current_question_index >= len) {
// returning anything prevents invalid set
return "index is out of bounds";
}
}
},
hasNextQ: function() {
var next_ind = this.get("current_question_index") + 1;
// use the logic we already created, in validate() but
// convert it to a bool. NOTE in javascript:
// !"stuff" === false
// !undefined === true
return !this.validate({current_question_index: next_ind});
},
nextQ: function() {
var next_ind = this.get("current_question_index") + 1;
// validate() will prevent us from setting an invalid index
return this.set("current_question_index", next_ind);
}
});