为父级调用渲染的主干子视图

Posted

技术标签:

【中文标题】为父级调用渲染的主干子视图【英文标题】:Backbone subview calling render for parent 【发布时间】:2015-07-17 13:24:18 【问题描述】:

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

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 并且父母的意见根 el 也是孩子的 *e*` 的父母,它也会被触发。 @Jack 我刚刚阅读了更多内容,似乎模型上的事件会冒泡到其父集合中。这将导致父级重新渲染。是否可以停止事件传播? 不完全是,但在您的事件回调中,您应该能够看到触发事件的原因并采取相应措施。那就是说,如果您不想采取行动,为什么您的集合视图会监听模型 expand 事件? @Jack 集合现在显式监听模型更改事件。显然,模型更改事件将启动其父集合的更改事件。所以我正在更改模型上的一个属性,该属性又发送一个事件来表示集合已更改,这反过来又重新渲染了父视图。 ***.com/questions/9951222/… 也许您应该听听您感兴趣的特定(或多个特定)事件(例如this.listenTo(this.collection, 'change:someProperty',this.render);,而不是听集合中的任何模型更改事件 【参考方案1】:

发生这种情况的方式有两种,一种是您正在收听集合中的主干事件,另一种是正在触发的 DOM 事件。

对于主干事件,如果您查看documentation,您会发现在集合中的模型上触发的事件也会在集合本身上触发

在集合中的模型上触发的任何事件也将 为方便起见,直接在集合上触发。这让你 监听任何模型中特定属性的变化 集合,例如:documents.on("change:selected", ...)

既然如此,您应该检查事件回调是否要对其采取行动(查看是什么触发了它,可能在触发事件时传入extra flag),或者确保您只是在听您有兴趣采取行动的特定事件。例如,您可能想听听更具体的版本 (change:someProperty),而不是听您收集通用的 change 事件。

使用 DOM 事件,如果您在 parents 视图中监听与孩子视图中相同的选择器,则很容易发生这种情况,因为父级的根 el 也是孩子的el

【讨论】:

以上是关于为父级调用渲染的主干子视图的主要内容,如果未能解决你的问题,请参考以下文章

子视图主干渲染上的事件

将 UIViewController 的视图调整为父 UIWindow 的边界

我应该或可以为父级中的子解析器获取数据吗?

访问父主干视图的属性

初始加载时主干视图未正确显示

React,是不是在父级上渲染会使子级重新渲染?