2012-05-30 55 views
2

我有一个相当简单的表格,使用Backbone Marionette CompositeView创建。该表的唯一要求是显示数据并允许用户通过单击标题行对其进行排序。在对表进行排序时,用于排序标题列的列标有类,以允许使用CSS显示箭头(例如'class =“sort asc”')。骨干木偶复合视图“事件僵尸”

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

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

这里的复合视图代码(从一个借用德里克贝利的样品小提琴的):

// 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的原始演示小提琴的叉证明问题可以在这里找到: http://jsfiddle.net/ccamarat/9stvM/14/

我蜿蜒了一下。我的问题是,我似乎有一个产生了僵尸视图的种类;这是一个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 
+0

你能更具体地了解问题吗?你已经以非常详细的方式提到了几个潜在的问题,但是只提出一个非常简短的问题,没有详细说明僵尸视图。你想解决哪个问题?你为什么认为你有僵尸的观点?你看到什么僵尸,在哪里? –

+0

也 - 我已经在最新版本的Chrome中运行您的示例小提琴,并且它工作正常。你说DOM没有更新的评论......当我运行它时,它已经被更新了。你使用什么浏览器/版本? –

+0

如果听起来有不止一个问题比我做了一个糟糕的工作来解释我自己。唯一的问题是我称之为僵尸视图。我称之为的原因是,至少在我的设置中,在第一个断点(使用event.target)更新的元素*不是*与第二个元素相同(使用this。$ el.find( ))。我正在使用最新版本的Chrome进行测试,并且我已经能够在两台不同的计算机上进行两次复制。 –

回答

2

我没有看到一个僵尸观点的证据。

我创建了一个代码的分支,并放入了一些额外的日志记录来检查视图实例,并且我没有看到任何僵尸。每次都使用相同的GridView实例。孩子们的意见在每次分类时都会正确关闭。

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

问题您眼见为实可能通过使用target = $(e.target)targetb = this.$(...)造成的。这些是两个非常不同的陈述,从DOM元素的两个完全不同的来源开始工作。

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

第二次使用的targetB = this.$(...)使用骨干视图的$el做一个发现:this.$el.find("...")这是会返回基于视图的EL结果。视图的$ eL恰好包含属于DOM的元素。但$ el与e事件不是同一个对象,因此您将永远不会以target === targetb为真。

......除非我完全误解了这个问题(现在看起来很可能),我认为这里没有问题。

+0

Your fiddle让我思考了调用sort()时会发生什么 - 底层集合发生了变化,触发了所有子视图的关闭 - 这是有道理的。但是,我并不期望它重置标题行,但这正是发生的情况。在调用'event.target'后,'sort()'不再指向DOM上的一个元素,因为'render()'操作调用'renderModel()',它从模板重新生成视图,销毁'event.target '在这个过程中。 –

+0

所以我创建了一个孤立的引用,而不是僵尸视图。我可以通过从CollectionView而不是复合视图继承,重写initialize()函数并在模板中手动读取。 感谢您的时间! –

+0

我现在看到......发生这种情况是因为CompositeView从CollectionView扩展而来,并且CollectionView有一个内置的事件处理程序,通过在集合重置时调用.render方法来重新呈现该事件处理程序。排序集合会重置集合(我认为),因此整个合成视图会重新呈现。你可以重写复合视图的'initialEvents'方法来改变这种行为:http://derickbailey.github.com/backbone.marionette/docs/backbone.marionette.html#section-21链接是CollectionView,但只是添加该方法给你的CompositeView覆盖。 –