第一次加载

时间:2015-10-19 18:55:57

标签: javascript backbone.js

我对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(); 

我的问题是,当我第一次到达主路线时,我正在使视图渲染功能运行两次。因为首先是提取正在调用它,并且路由也在调用它。

我需要从获取成功或路由中删除该调用,但是当我这样做时,我在初始加载时没有得到任何结果,我必须导航到不同的路由并返回。

你应该怎么做到这一点?所以我可以获取结果一次,然后通过获取成功的路径显示它们,但是当用户导航到路径时也会在路径中显示它们。

我希望这有道理吗?

任何帮助都会很棒。

1 个答案:

答案 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;
&#13;
&#13;