Marionette ItemView无法从集合视图重新渲染模型

时间:2014-05-20 19:53:11

标签: backbone.js marionette

我创建了一个传递集合视图和集合的集合。该集合引用了我创建的模型。在获取集合时,项目会成功呈现,但是当模型更改时,itemViews不会按预期重新呈现。

例如,tweetCollectionView中的itemAdded函数被调用两次(在fetch上添加了两个模型)但是即使parse函数随着时间的推移为这些模型返回不同的属性(我假设这会调用集合上的change事件) ,或者特别是模型上的更改事件,我试图在ItemView中捕获)itemChanged永远不会被调用,并且itemViews永远不会被重新渲染,我希望在捕获itemViews模型更改事件时完成。

代码如下:

    function TweetModule(){

            String.prototype.parseHashtag = function() {
                return this.replace(/[#]+[A-Za-z0-9-_]+/g, function(t) {
                    var tag = t;
                    return "<span class='hashtag-highlight'>"+tag+"</span>";
                });
            };

            String.prototype.removeLinks = function() {

                var urlexp = new RegExp( '(http|ftp|https)://[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:/~+#-]*[\w@?^=%&amp;/~+#-])?' );

                return this.replace( urlexp, function(u) {
                    var url = u;
                    return "";
                });

            };

            var TweetModel = Backbone.Model.extend({
                idAttribute: 'id',
                parse: function( model ){
                    var tweet = {},
                        info = model.data;

                    tweet.id = info.status.id;
                    tweet.text = info.status.text.parseHashtag().removeLinks();
                    tweet.name = info.name;
                    tweet.image = info.image_url;
                    tweet.update_time_full = info.status.created_at;
                    tweet.update_time = moment( tweet.update_time_full ).fromNow();

                    return tweet;
                }
            });

            var TweetCollection = Backbone.Collection.extend({
                model: TweetModel,
                url: function () {
                    return '/tweets/game/1'
                }
            });

            var TweetView = Backbone.Marionette.ItemView.extend({

                template: _.template( require('./templates/tweet-view.html') ),

                modelEvents:{
                    "change":"tweetChanged"
                },
                tweetChanged: function(){
                    this.render();
                }
            })


            var TweetCollectionView = Marionette.CompositeView.extend({
                template: _.template(require('./templates/module-twitter-feed-view.html')),
                itemView: TweetView,
                itemViewContainer: '#tweet-feed',
                collection: new TweetCollection([], {}),
                collectionEvents: {
                    "add": "itemAdded",
                    "change": "itemChanged"
                },
                itemAdded: function(){
                    console.log('Item Added');
                },
                itemChanged: function(){
                    console.log("Changed Item!");
                }
            });

            this.startInterval = function(){
                this.fetchCollection();
                this.interval = setInterval( this.fetchCollection, 5000 );
            }.bind(this);

            this.fetchCollection = function(){
                this.view.collection.fetch();
                this.view.render();
            }.bind(this);

            //build module here
            this.view = new TweetCollectionView();
            this.startInterval();

    };

我可能会对Marionette处理事件冒泡做出假设,但根据文档,我没有看到任何指向此事的内容。

2 个答案:

答案 0 :(得分:0)

CollectionView内,执行

this.collection.trigger ('reset') 

添加模型后。

这将触发onRender ()中的ItemView方法重新渲染。

答案 1 :(得分:0)

我知道我回答了一个老问题,但由于它有很多观点,我以为我会正确回答。另一个答案并没有解决代码的问题及其解决方案(触发重置)将强制所有孩子重新渲染,这既不是必需的也不是理想的。

OP代码的问题是change不是集合事件,这就是永远不会调用itemChanged方法的原因。要监听的正确事件是update,根据Backbone.js catalog of events

  

...在添加任意数量的模型后触发单个事件   或从集合中删除。

问题并未说明正在使用的Marionette的版本,但至少会回到2.0.0版CollectionView将智能地重新呈现集合addremovereset事件。来自CollectionView: Automatic Rendering

  

当视图集合为&#34; reset&#34;时,视图将调用render   自己并重新渲染整个系列。

     

将模型添加到集合时,集合视图将会   将一个模型渲染到子视图集合中。

     

从集合中删除模型(或销毁/删除)时,   集合视图将销毁并删除该模型的子视图

行为is the same in v3