【问题标题】:Why does jQuery's $().each() function seem to be losing track of the DOM?为什么 jQuery 的 $().each() 函数似乎失去了对 DOM 的跟踪?
【发布时间】:2010-03-29 14:00:03
【问题描述】:

我最近开始遇到一个非常奇怪的问题。老实说,除了展示它之外,我不完全确定如何描述它。

以下是相关的 HTML:

<div class="component container w100 noEdit" id="contentWrapper"> 
<div class="component container w50" id="container1"> 
   <div class="component text w50" id="text1"> 
      Text1 
   </div> 
</div> 
<div class="component container w25" id="container2"> 
   Container2 
</div> 
<div class="component container w25" id="container3"> 
   Container3 
</div> 
<div class="component container w25" id="container4"> 
   Container4 
</div> 
</div> 

以及相关的 JavaScript:

$(document).ready(function () { 
   //Add the Grab Bar to container components on the page. 
   $('.component').each(wrapComponentForEdit); 
   $('#contentWrapper').sortable(); 
   $('#contentWrapper').disableSelection(); 
}); 

var wrapComponentForEdit = function() 
{ 
   if (!$(this).hasClass('noEdit')) { 
      $(this).html('<div class="componentBorder">' + $(this).html() + '</div>'); 
      $(this).prepend('<div class="grabBar_l"><div class="grabBar_r"><div class="grabBar"></div></div></div>'); 
      alert($(this).attr('id')); 
   } 
} 

这样做的最终结果是,我看到容器 1、text1、container2、container3、container 4 的警报弹出。然而只有容器(而不是文本)最终会出现 $() 的视觉变化。 each() 应该做。

有人知道到底发生了什么吗?

谢谢!

编辑 - 一种不同的方法,但仍然失败

我试过了,结果一样:

$(document).ready(function () {
    //Add the Grab Bar to container components on the page.
    var matched = $('.component');
    var componentCount = $(matched).size();
    for (i = 0; i < componentCount; i++)
    {
        wrapComponentForEdit($(matched).eq(i));
    }
    $('#contentWrapper').sortable({ handle: '.grabBarBit', tolerance: 'pointer'});
    $('#contentWrapper').disableSelection();
});

var wrapComponentForEdit = function(component)
{
    if (!$(component).hasClass('noEdit')) {
        $(component).html('<div class="grabBar_l grabBarBit"><div class="grabBar_r grabBarBit"><div class="grabBar grabBarBit"></div></div></div><div class="componentBorder">' + $(component).html() + '</div>');
        alert($(component).attr('id'));
    }
}

编辑 2:另一种替代方法,但这种方法有效

我尝试了另一种做事方式,并且这种方式有效。然而,最初的问题仍然存在。从这种新方法的工作原理来看,在我看来,DOM 正在更新,但 jQuery 并没有随之更新,因此它失去了对子元素的跟踪。

$(document).ready(function () {
    //Add the Grab Bar to container components on the page.
    var componentCount = $('.component').size();
    for (i = 0; i < componentCount; i++)
    {
        wrapComponentForEdit($('.component').eq(i));
    }
    $('#contentWrapper').sortable({ handle: '.grabBarBit', tolerance: 'pointer'});
    $('#contentWrapper').disableSelection();
});

var wrapComponentForEdit = function(component)
{
    if (!$(component).hasClass('noEdit')) {
        $(component).html('<div class="grabBar_l grabBarBit"><div class="grabBar_r grabBarBit"><div class="grabBar grabBarBit"></div></div></div><div class="componentBorder">' + $(component).html() + '</div>');
        alert($(component).attr('id'));
    }
}

【问题讨论】:

  • 您使用 div 包装而不是仅仅使用 .addClass() 的任何特殊原因?
  • div 的顺序。我总是患有非常严重的divitis,但在这里我认为这是有道理的——grabBar 的边缘是圆形的,需要流畅地改变宽度。圆角边缘还要求组件周围的边框位于grabBar 下方。我使用 javascript 执行此操作的原因是这些部分仅在某些情况下需要。
  • 我看不出问题出在哪里。包装 div 看起来就像它们被很好地应用于所有元素。你确实有这个错误:$("#contentWrapper").sortable is not a function
  • 我没有将它包含在我的示例中,但是 jQuery UI 包含在我的代码中,因此该错误不是问题。每当我在本地运行它时,包装 div 将应用于 container1 2 3 和 4,但不是 text1。

标签: jquery dom


【解决方案1】:

这让我想起另一个问题

wait until previous .append() is complete (jquery).

当为下一个(嵌套的)html 标记再次调用该函数时,也许 .html 或 .prepend 命令仍在运行。

当您像这样删除外部组件类时,看看问题是否消失:

<div class="container w50" id="container1"> 
   <div class="component text w50" id="text1"> 
      Text1 
   </div> 
</div>

如果这确实消除了您的问题,您将需要想出一种更慢的方法来更新 html,等待之前的更改完成。

请参阅43,439 reasons to use append() correctly 了解有关 Append 的更多信息(其中有一些好主意)

【讨论】:

  • 从外部元素中移除组件类实际上使子元素呈现正确。我还尝试将所有内容压缩成一个 $().html() 而不做任何更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-01
  • 2015-04-03
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
相关资源
最近更新 更多