1

我的最终目标是将 JSON 数据附加到ul#tweets,每个作为单独的隐藏列表项。然后,随着时间的推移,它们将一一出现,在屏幕上可见/显示,然后从ul#tweets列表中删除。

一旦隐藏项目的数量低于一定数量,我想重新附加 JSON 数据。发生这种情况时,我不担心重复的项目。

我尝试通过创建一个具有超时的函数来设置测试,以便每 5 秒将 JSON 数据附加到列表中。

但是,尽管我的应用程序可以很好地加载页面加载的初始数据,但是当我创建要在其中运行的函数时$(document).ready({})-它将无法正常工作。

但是,我确实知道,我可以在页面加载后在控制台中手动附加 JSON 数据(与下面的代码相同,而无需将其包装在函数或 doc.ready 中)。

谢谢您的帮助!

功能:

$(document).ready(function(){
   updateTweets = function() {

    newTweets = new Tweets();
    newTweets.fetch();

    newTweets.each( function(tweet) {

      console.log('test'); // this doesn't work
      view = new TweetView({ model:tweet });
      $('#tweets').append(view.render().el);
    });

    setTimeout(updateTweets, 5000);
  };
  updateTweets();

});


这是我的代码

// MODEL
window.Tweet = Backbone.Model.extend({});

// COLLECTION
window.Tweets = Backbone.Collection.extend({ model: Tweet, url: '/tweets' });

// SET GLOBAL VARIABLE FOR NEW TWEETS COLLECTION
window.tweetList = new Tweets();

$(document).ready(function() {

// MODEL VIEW
window.TweetView = Backbone.View.extend({
    tagName: 'li',
    className: 'tweet',

    initialize: function() {
        _.bindAll(this, 'render');
        this.model.bind('change', this.render);
        this.template = _.template($('#tweet-template').html());
    },

    render: function(){
        var renderedTweets = this.template(this.model.toJSON());
        $(this.el).html(renderedTweets);

        return this;
    }
});

// COLLECTION VIEW
window.TweetListView = Backbone.View.extend({

  template: _.template($('#tweet-list-template').html()),

  initialize: function() {

    _.bindAll(this, 'render');
    this.collection.bind('reset', this.render);

  },

  render: function() {
    var $tweets,
    collection = this.collection;

    $(this.el).html(this.template({}));
    $tweets = this.$('#tweets');
    collection.each(function(tweet){
      var view = new TweetView({
        model: tweet,
        collection: collection
      });
      $tweets.append(view.render().el);
    });
    return this;
  }
});

// ROUTER
window.TweetListDisplay = Backbone.Router.extend({
  routes: {
    '': 'home'
  },
  initialize: function(){
    this.tweetListView = new TweetListView({
      collection: window.tweetList
    });
  },
  home: function() {
    var $container = $('#container');
    $container.empty();
    $container.append(this.tweetListView.render().el);
  },
});

// DECLARE AND START APP
window.app = new TweetListDisplay();
Backbone.history.start();

}); // close $(document).ready({});
4

2 回答 2

1

你在这里调用 fetch

newTweets.fetch();

然后在开始处理集合之后,就好像它已经被填充一样,在这里

newTweets.each( function(tweet) {

  console.log('test'); // this doesn't work
  view = new TweetView({ model:tweet });
  $('#tweets').append(view.render().el);
});

fetch是一个 ASYNCHRONOUS 操作,这意味着在你触发它之后,程序的其余部分将立即继续执行,无论由 ajax 发起的调用fetch是否返回。因此,当您开始处理集合时,您的 fetch 尚未返回并且集合仍然是空的。

有两种方法可以纠正这种情况。让我们首先创建一个processCollection对集合执行您想要的功能的函数:

var processCollection = function () {
  newTweets.each( function(tweet) {

    console.log('test'); // this doesn't work
    view = new TweetView({ model:tweet });
    $('#tweets').append(view.render().el);
  });
};

1 回调函数(我不喜欢这些)

newTweets.fetch(success: processCollection);

现在processCollection将在获取成功后立即调用。

2 绑定到事件(我更喜欢这个)

newTweets.on('reset', processCollection);
newTweets.fetch();

当 fetch 成功返回时,它将填充集合并触发reset-event。这是绑定处理事件的好地方,因为您知道现在集合已填充。此外,我发现事件的范围问题比回调的问题要少一些。

希望这可以帮助!

于 2012-09-11T10:05:00.620 回答
0

你不能打电话;

 newTweets.fetch();

然后立即开始处理集合,就好像它可以使用一样.. 它需要时间.. fetch 调用是异步的.. 它在控制台中工作的原因是它需要时间来为控制台准备输出.. 并且 fetch 确实确实完结了。。

您应该为 fetch 提供一个成功回调,如下所示:

 newTweets.fetch({success: function(){//process collection}});
于 2012-09-11T09:53:02.547 回答