.clone(true,true) + .remove() 的 Jquery ui 奇怪行为

Posted

技术标签:

【中文标题】.clone(true,true) + .remove() 的 Jquery ui 奇怪行为【英文标题】:Jquery ui weird behaviour with .clone(true,true) + .remove() 【发布时间】:2012-03-17 21:20:01 【问题描述】:

我在使用 jquery-ui 和 jquery .clone()、remove() 时遇到了奇怪的行为。 我正在使用 jquery 1.7 和 jquery-ui 1.8.16。 问题是当我使用 remove() 函数从深层克隆元素中删除元素时,删除会通过从 DOM 中的元素中删除可拖动属性来影响克隆元素和文档中的相应元素。我不确定我是否做错了什么,但在我看来,要么是我对 clone(true,true) 工作原理的误解,要么是 jquery-ui 中的错误。

考虑以下

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js" type="text/javascript"></script>
  <script type="text/javascript">
  $(document).ready(function() 
    $('#testp').draggable();
    //the following line causes the draggable classes to be removed from the document
    //as well as the cloned object ,the expected behaviour is that that #testp will be 
    //removed only from the clone...
          var test = $("#test")
           .clone(true,true)
           .find('#testp')
           .remove()
           .end(); //some more manipulation here
        );
  </script>
</head>
<body>
  <div id="test">
    <p id="testp">some text</p>
  </div>
</body>
    </html>

更新: 似乎 .clone(true,true) 仍然在克隆和原始之间共享一些数据。 即使使用类选择器更改 ids/应用 .draggable() 并且不从 dom 中删除任何元素,拖动克隆也会移动原始元素并且不会影响克隆(正如人们所想的那样)。其他处理程序(如 click 等)已正确克隆

在看到一些关于使用 (true,true) 和可拖动插件克隆 div 问题的帖子后,我决定避免克隆 div 复制等,而只使用 detach() 并重新附加作为解决方法。

注意其他尝试使用 clone(true,true) 克隆 div 并应用了 draggable() 插件的人: 如果您 clone(true,true) 一些数据将被复制到克隆中,并且通过对其应用 draggable() 您将拖动原始数据,我想这不是您打算做的。 而是做一个浅的 .clone() 然后将 draggable() 绑定到克隆。

【问题讨论】:

你能把它添加到jsfiddle中吗 【参考方案1】:

尝试单独的语句:

var test = $("#test");
test.clone(true,true).appendTo("whatever").find('#testp').remove();

PS:clone() 和 remove() 在 jQuery 核心中。 jQuery UI 的存在不应该影响它们,但一定要尝试不安装 UI。

【讨论】:

它不起作用。我想将克隆的元素分配给一个变量。并在以后重新分配它。(我还不想将它附加到文档中) var test = $("#test"); var copy = test.clone(true,true).find('#testp').remove().end(); //最后一行导致相同的行为 我还应该注意,其他行为会保留在原始文件上,例如保留点击事件。那是我认为它与 jquery-ui 更相关 问题可能是由于使用了ids。克隆将具有相同的 id,因此您需要在克隆后更改它们或改用类。 另请注意,.clone() 的 jQuery 文档包括附带条件“但是,元素数据中的对象和数组不会被复制,并且将继续在克隆元素和原始元素之间共享。深入复制所有数据,手动复制每一个:...”。 draggable() 可能需要考虑这一方面。 注意 clone() 文档中的以下注释:从 jQuery 1.5 开始,可以选择使用 deepWithDataAndEvents 增强 withDataAndEvents 以复制克隆元素的所有子元素的事件和数据。这就是为什么我使用 .clone(true,true)【参考方案2】:

请查看:What is the most efficient way to deep clone an object in JavaScript?

请注意,您可能必须取消绑定事件克隆并在克隆期间重新应用它们 - 在某种程度上取决于您的操作方式,如果您在应用时将事件应用于原始源,则可能需要取消绑定源您的新应用选择包括原件。

在您的情况下,您正在使用 id 选择器,然后将其删除 - 它将删除它找到的第一个 id 实例。

您可能需要执行以下操作:(为清楚起见,详细版本)

var test = $("#test");
var newtest = test.clone(true, true);
newtest.find('#testp').remove();
newtest.attr('id', 'newtest');
newtest.appendTo("#whatever");

也许在这里重新绑定...

看这个例子:http://jsfiddle.net/MarkSchultheiss/yfD3r/

【讨论】:

实际上它不会删除 dom 上的 ID。只有可拖动的属性实际上我试图避免重新绑定,这就是为什么这种操作......我试图实现的是一个具有可拖动元素的编辑器,它在页面之间“ajax 导航”时保留它的所有行为。我发现我可以在 dom 之外克隆导航器并在 ajax 完成后重新附加它。问题是另一个编辑器会尝试加载一些 ajax 调用,这就是我要删除的内容 所以,你的问题似乎已经改变了 注意:事件和 draggable 之间存在差异,它更像是一个“小部件”而不是诸如“click”之类的事件,您可能需要在重新插入后重新附加 draggable之前从 DOM 中删除。

以上是关于.clone(true,true) + .remove() 的 Jquery ui 奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

jQuery-DOM操作之复制替换包裹节点

.clone事件当你克隆的时候,DOM节点是克隆出来了,但是克隆出来的节点不能运行时事件 ...

tsc 不排除 node_modules

jQuery clone( ) 方法

jQuery文档操作之克隆操作

jQuery学习-克隆节点