Backbone Marionette CompositeView“Event Zombie”

时间:2012-05-30 03:44:37

标签: jquery backbone.js underscore.js marionette

我有一个使用Backbone Marionette CompositeView创建的相当简单的表。此表的唯一要求是它显示数据并允许用户通过单击标题行对其进行排序。对表进行排序时,用于对标题列进行排序的列标有类,以允许使用CSS显示箭头(例如'class =“sort asc”')。

问题是:当单击标题行时,传递给回调的元素(通过event.target)不是DOM上的表的一部分。相反,使用Chrome的调试工具,似乎目标元素实际上是模板脚本块的一部分,而不是用户实际看到的元素。

我现在最好的解决方法是通过从模板中的克隆中检索唯一信息来查找实际附加到DOM的元素。

这是复合视图代码(借自Derick Bailey的样本Fiddle之一):

// The grid view
var GridView = Backbone.Marionette.CompositeView.extend({
    tagName: "table",
    template: "#grid-template",
    itemView: GridRow,

    events: {
        'click th': 'doSort'
    },

    doSort: function(event) {
        var target = $(event.target);
        this.collection.sortByField(target.data('sortby'));

        target.parent('tr').find('.sort').removeAttr('class');
        target.addClass('sort ' + this.collection.sortdir);
        debugger; // NOTE: no change to elements in the DOM. WTH?

        target = this.$('[data-sortby=' + target.data('sortby') + ']');
        target.parent('tr').find('.sort').removeAttr('class');
        target.addClass('sort ' + this.collection.sortdir);
        debugger; // NOTE: DOM updated.
    },

    appendHtml: function(collectionView, itemView) {
        collectionView.$("tbody").append(itemView.el);
    }
});

模板也很简单:

<script id="grid-template" type="text/template">
    <thead>        
        <tr>
            <th data-sortby="username">Username</th>
            <th data-sortby="fullname">Full Name</th>
        </tr>
    </thead>
    <tbody></tbody>
</script>

可以在此处找到Derek原始演示Fiddle的一个分支,以演示该问题: http://jsfiddle.net/ccamarat/9stvM/14/

我蜿蜒了一下。我的问题是,我似乎产生了各种各样的Zombie视图;这是一个jQuery / Backbone / Underscore错误,还是我只是这样做错了?

**编辑** 这是控制台输出,显示了两个元素的不同父层次结构:

console.log(target, targetb):
    [<th data-sortby="username" class="sort asc">Username</th>] [<th data-sortby="username">Username</th>]

console.log(target.parents(), targetb.parents()):
    [<tr>…</tr>, <thead>…</thead>] [<tr>…</tr>, <thead>…</thead>, <table>…</table>, <div id="grid">…</div>, <body>…</body>, <html>…</html>]

console.log(target === targetb):
    false

1 个答案:

答案 0 :(得分:2)

我没有看到任何僵尸视图的证据。

我创建了一个代码分支并添加了一些额外的日志来检查视图实例,我没有看到任何僵尸。每次都使用相同的GridView实例。每次分类时,儿童观点都会被正确关闭。

http://jsfiddle.net/derickbailey/hadbf/4/

您看到的问题可能是由target = $(e.target)targetb = this.$(...)引起的。这两个非常不同的陈述,来自两个截然不同的DOM元素来源。

target = $(e.target)的第一次使用是直接从DOM运行的。您正在目标上运行一个选择器,该选择器只是将该DOM元素包装在jQuery选择器对象中。

targetB = this.$(...)的第二次使用是使用Backbone View的$el进行查找:this.$el.find("..."),它将根据视图的EL返回结果。视图的$ eL恰好包含属于DOM的元素。但$ el与e事件不是同一个对象,因此您永远不会以target === targetb为真。

......除非我完全误解了这个问题(这似乎很可能在这一点上),我认为这里不存在问题。