Backbone子视图调用父视图的渲染函数

3

我有一个backbone页面,其行为如下。

Collection - > Models -> Views

我有一个包含N个搜索结果的集合。每个模型都与一个视图实例相关联,这个视图在本例中是显示的数据行。

我希望能够从“详细信息”视图切换到“高级”视图,后者包含更多信息。目前,父视图为每个模型呈现了N个视图。我可以通过更新模型并监听更改事件来切换状态,然后仅重新渲染我点击的视图的部分。但是我注意到了一个问题。问题是视口跳转到页面的顶部,这不是很好的用户体验。

在调试时,我注意到了一些奇怪的东西

父视图(包含搜索结果的页面)的渲染函数被调用,这反过来又调用了每个行的渲染函数。我认为这就是导致每个子视图重新渲染的原因。

以下是一些代码示例,以演示问题:

// The child view's render and initialis
    var SearchInviteRow = Backbone.View.extend({

    tagName:  "invite-section-result-row",

    initialize: function(params){
        this.template = templateHTML;
        this.extendedTemplate = extendedTemplate;
        this.listenTo(this.model, 'change', this.render);
    },

    events : {
        "click .toggle-attachments" : "renderWithAttachments"
    },   

    render: function(){
        var view = this, render;
        var that = this;

        if(!this.model.get("expand")){
            var rendered = Mustache.render(view.template, that.model.toJSON());
            this.$el.html(rendered);
        } else {

            var rendered = Mustache.render(view.extendedTemplate, that.model.toJSON());
            this.$el.html(rendered);
        }

        return this;
    },  

    close: function(){
        this.remove();          
    },

    renderWithAttachments: function(){
        if( !this.model.get("expand") ) {
            this.model.set( {"expand" : true } );
            this.model.getAttachments();
        } else {
            this.model.set( {"expand" : false } );
        }

    }
});

这是父元素渲染的一部分,用于迭代集合并将行追加到搜索磁贴中。
   for (var i = 0; i < this.collection.length; i++) {

            view.subViewArray[i] = new SearchInviteRow({
                model: this.collection.at(i)
            });

            this.$(".invite-section-inside").append(view.subViewArray[i].render().el);

        }

我无法理解的是为什么父组件的渲染函数会被调用,这导致了其他问题。

你还没有发布你的父视图或标记,所以很难确定,但如果你在事件哈希中使用相同的选择器,那么由于事件委托给了根元素el,而父视图的根元素也是子元素e的父元素,它也会被触发。 - Jack
@Jack 我刚刚读了一些内容,似乎模型上的事件会冒泡到它们父级的集合。这将导致父级重新渲染。有没有可能停止事件传播? - Sam Marland
不完全是,但在您的事件回调中,您应该能够看到是什么触发了事件,并相应地采取行动。话虽如此,如果您不想采取行动,为什么您的集合视图要监听模型的展开事件呢? - Jack
@Jack,现在集合明确地监听模型更改事件。显然,模型更改事件将触发其父集合的更改事件。因此,我正在更改模型上的一个属性,这将发送一个事件来表示集合已更改,进而重新呈现父视图。https://dev59.com/bGLVa4cB1Zd3GeqPtir6 - Sam Marland
@Jack,就是这样,我停止了对集合更改事件的监听,只监听排序事件,这就是我现在所需要的。如果你想发表答案,我会接受它。 - Sam Marland
显示剩余2条评论
1个回答

1
有两种情况会发生这种情况,一种是如果您正在收听集合上的backbone事件,另一种是如果被触发的是DOM事件。
对于backbone事件,如果您查看文档,您将看到在集合中触发的模型上触发的事件也将在集合本身上触发。
任何在集合中的模型上触发的事件也将方便地直接在集合上触发。这使您能够监听集合中任何模型中特定属性的更改,例如:documents.on(“change:selected”,...)
既然如此,在事件回调中,您应该检查是否要采取行动(查看触发它的内容,可能在触发事件时传递额外标志),或者确保您仅侦听您感兴趣的特定事件。例如,您可能不想侦听集合的通用change事件,而是希望侦听其更具体的版本(change:someProperty)。
使用DOM事件时,如果你在父视图和子视图中监听相同的选择器,那么很容易发生这种情况,因为父级根元素`el`也是子元素`el`的父元素。请保留HTML标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接