如何克隆已被 jQuery UI Widget 绑定的元素?

Posted

技术标签:

【中文标题】如何克隆已被 jQuery UI Widget 绑定的元素?【英文标题】:How to clone elements that have been bound by a jQuery UI Widget? 【发布时间】:2012-04-01 07:13:17 【问题描述】:

以下代码无法正确克隆输入元素。单击/关注克隆的输入会​​在原始输入上打开日期选择器。

http://jsfiddle.net/musicisair/YUkZw/

<input>
<script>
    var input = $("input").datepicker();
    $("body").append("<br>Input 2: ").append(
        input.clone(true);
    );
</script>

是否有克隆与 jQuery UI 小部件绑定的元素的正确方法?如果有,是什么?

【问题讨论】:

【参考方案1】:

通常,绑定到原始元素的任何事件处理程序都不会 复制到克隆。可选的 withDataAndEvents 参数允许 我们改变这种行为,并改为复制所有 事件处理程序也绑定到元素的新副本。作为 jQuery 1.4,所有元素数据(由 .data() 方法附加)也是 复制到新副本。

但是,元素数据中的对象和数组不会被复制和 将继续在克隆元素和原始元素之间共享 元素。要深度复制所有数据,请手动复制每个数据:

var $elem = $('#elem').data( "arr": [ 1 ] ), // Original element with attached data
    $clone = $elem.clone( true )
    .data( "arr", $.extend( [], $elem.data("arr") ) ); // Deep copy to prevent data sharing

从 jQuery 1.5 开始,withDataAndEvents 可以选择增强 deepWithDataAndEvents 复制所有子节点的事件和数据 克隆的元素。

来源:http://api.jquery.com/clone/

我相信您正在寻找上面的代码,它实际上复制了与元素关联的数据,而不是在元素之间共享数据。

更新

在搞砸了几分钟后,这就是我想出的:

//create original datepicker
var $input = $("input").datepicker(),

//clone the datepicker, copy the data from the original, and change the ID of the new element
    $clone = $input.clone(true).data( "datepicker", $.extend( true, , $input.data("datepicker") ) ).attr('id', 'test-id');

//now change the references in the data for the clone to point to the clone
$clone.data('datepicker').input = $clone;
$clone.data('datepicker').id = 'test-id';


//add the clone to the DOM
$("body").append("<br><br><br>Input 2: ").append(
    $clone
);
​

还有一个演示:http://jsfiddle.net/YUkZw/5/

【讨论】:

@SKS 感谢您的评论。我粘贴了错误的代码,如果您为克隆扩展 datepicker 数据而不是仅仅复制它,那么每个元素都会获得自己的一组数据(请参阅:jsfiddle.net/YUkZw/5)。然后对于克隆,您必须在其 datepicker 数据中设置引用以引用克隆。 哈哈.. 你做到了.. 但不是工作太多.. 我宁愿建议在输入 2 上再次初始化数据选择器:P.. 干得好。 +1 @SKS 我同意,但弄清楚还是很有趣:) 这看起来很有希望。我想知道$.fn.clone 是否可以扩展,以便deep (deepWithDataAndEvents) 克隆会自动处理这个问题。我的用例比我在问题中提供的 jsFiddle 示例复杂得多。 @DavidMurdoch 您可以使用.clone()$.fn.customClone = function ($ele) return $ele.clone(true); 创建自己的函数。当然这个例子没有任何好处,但是你可以在这个自定义函数中做额外的工作,这样你就可以调用$clone = $input.customClone();【参考方案2】:

这是我的窍门。

如果您必须克隆具有小部件的元素,请不要将小部件绑定到 document.ready。而是在每次元素获得焦点时重新生成小部件。

$(document).ready(function()
    $("[type=date]").focusin(function()
        $("[type=date]").not(this).datepicker("destroy");
        if($(this).data("datepicker") == null) 
            $(this).datepicker(dateFormat: 'yy-mm-dd');
        
    );
);

【讨论】:

以上是关于如何克隆已被 jQuery UI Widget 绑定的元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何调整克隆的 jQuery UI 元素的大小(图片)

Jquery UI

在 jQuery UI 中克隆可拖动对象时,如何将数据和事件传输到新元素?

在 jquery drop UI 中,如何使用正确的鼠标位置将拖动元素克隆到放置位置?

jquery ui widget原理解析

1分钟看完 jQuery UI