我对 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();
}
});
记分卡 View :
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();
我的问题是,当我第一次到达主路线时, View 渲染函数运行了两次。因为首先 fetch 正在调用它,并且路由也正在调用它。
我需要从获取成功或路由中删除调用,但是当我这样做时,我在初始加载时没有得到任何结果,我必须导航到不同的路由并返回。
你应该如何实现这一目标?因此,我可以获取一次结果,然后通过获取成功的路线显示它们,而且当用户导航到它时也可以在 route 显示它们。
我希望这是有道理的?
任何帮助都会很棒。
最佳答案
首先,您的数据不应该知道它是如何呈现的,因此模型或集合中任何位置的 new View()
都是问题的明确标志。您的 View 应该观察数据并自行更新。
您的另一个可能的困惑来源是将 {trigger: true}
传递给您的路由器 navigate
方法。带来什么样的麻烦,在这篇经典的Backbone文章中详细解释了:Don’t Execute A Backbone.js Route Handler From Your Code .
现在,您绝对应该从集合中删除 View 渲染。相反,您的 View 应该了解集合并在数据更改时自行更新。
以下是我如何设置 View 来观看集合的示例:
/** 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();
<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>
关于javascript - 主干集合获取渲染在第一次加载时使用路由器运行两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33221817/