我对Backbone相当陌生,我正试图绕过路由器并从数据库中调用一个集合。
我有以下内容 系列:
var Scorecards = Backbone.Collection.extend({
model:Scorecard,
url:"http://localhost:3002/api/scorecards",
initialize:function(){
this.fetch({
success: this.fetchSuccess,
error: this.fetchError
});
},
fetchSuccess: function (collection, response) {
console.log("results");
if(collection.length>0) {
var view = new ScorecardsView({el:'#scorecards-container', model:scorecards});
view.render();
}
else{
var view = new NoScorecardsView({el:'#scorecards-container'});
view.render();
}
},
fetchError: function(collection, response) {
throw new Error("Failed to get scorecards");
}
});
路由器:
var ScorecardRouter = Backbone.Router.extend ({
routes: {
'' : 'home',
'create': 'createScorecard',
'edit': 'editScorecard'
},
home: function () {
console.log("Home view");
var view = new ScorecardsView({el:'#scorecards-container', model:scorecards});
view.render();
},
createScorecard: function () {
console.log('Create view');
var view = new CreateScorecardView({el:'#scorecards-container'});
view.render();
}
});
记分卡视图:
var ScorecardsView = Backbone.View.extend({
initialize: function(){
this.model.on('destroy', this.render, this);
},
render: function() {
console.log("Scorecard render");
var self = this;
this.$el.html(ScorecardContTemp);
this.model.each(function(scorecard){
var scorecardView = new ScorecardView({model:scorecard});
self.$('.scorecards-items tbody').append(scorecardView.render().$el);
});
},
events: {
"click #scorecard-create-btn" : "createScorecardView",
},
createScorecardView: function(e) {
e.preventDefault();
scorecardRouter.navigate('create', {trigger: true});
}
});
我用这个开始了
var scorecards = new Scorecards;
var scorecardRouter = new ScorecardRouter();
Backbone.history.start();
我的问题是,当我第一次到达主路线时,我正在使视图渲染功能运行两次。因为首先是提取正在调用它,并且路由也在调用它。
我需要从获取成功或路由中删除该调用,但是当我这样做时,我在初始加载时没有得到任何结果,我必须导航到不同的路由并返回。
你应该怎么做到这一点?所以我可以获取结果一次,然后通过获取成功的路径显示它们,但是当用户导航到路径时也会在路径中显示它们。
我希望这有道理吗?
任何帮助都会很棒。
答案 0 :(得分:1)
首先,您的数据不应该知道它是如何呈现的,因此模型或集合中任何位置的new View()
都是问题的确定标志。您的观点应该观察他们的数据并自行更新。
您的其他可能混淆源是将{trigger: true}
传递给您的路由器navigate
方法。在这个经典的Backbone文章中详细解释了带来了什么样的麻烦:Don’t Execute A Backbone.js Route Handler From Your Code。
现在,您肯定应该从集合中删除视图呈现。相反,您的视图应该知道集合并在数据更改时自行更新。
以下是我如何设置视图以观看收藏的示例:
/** Scorecard model */
var Scorecard = Backbone.Model.extend({
defaults: {
name: '',
email: ''
}
});
/** Scorecard View (I know it totally doesn't look like a scorecard, just an example view) */
var ScorecardView = Backbone.View.extend({
template: _.template('<%=name%>, <em><%=email%></em>'),
render: function(){
this.$el.html( this.template( this.model.toJSON() ) );
return this;
}
});
/** Collection */
var Scorecards = Backbone.Collection.extend({
model: Scorecard,
/** using fake api for the sake of this example to work */
url: "http://jsonplaceholder.typicode.com/users",
initialize:function(){
this.fetch({
success: this.fetchSuccess,
error: this.fetchError
});
},
fetchSuccess: function (collection, response) {
console.log("results:", collection);
},
fetchError: function(collection, response) {
throw new Error("Failed to get scorecards");
}
});
/** Scorecards view: */
var ScorecardsView = Backbone.View.extend({
initialize: function(){
this.collection.on('destroy', this.render, this);
/** render one added item whenever it comes to collection */
this.collection.on('add', this.addOne, this);
},
render: function() {
console.log("Scorecard render");
/** clean the items container,
which will be useful when items get destroyed
and we'll want to re-render whole collection */
this.$el.find('.scorecards-items').empty();
/** in case collection already has data, let's render it */
this.collection.each(this.addOne, this);
},
addOne: function(scorecard){
var scorecardView = new ScorecardView({ model: scorecard });
this.$('.scorecards-items').append(scorecardView.render().$el);
}
});
/** Router: */
var ScorecardRouter = Backbone.Router.extend ({
routes: {
'' : 'home'
},
home: function () {
console.log("Home view");
var view = new ScorecardsView({
el:'#scorecards-container',
collection: scorecards
});
view.render();
}
});
/** starting things off */
var scorecards = new Scorecards();
var scorecardRouter = new ScorecardRouter();
Backbone.history.start();
&#13;
<script src='http://code.jquery.com/jquery.js'></script>
<script src='http://underscorejs.org/underscore.js'></script>
<script src='http://backbonejs.org/backbone.js'></script>
<div id="scorecards-container">
<div class="scorecards-items"></div>
</div>
&#13;