【问题标题】:How to clone elements that have been bound by a jQuery UI Widget?如何克隆已被 jQuery UI Widget 绑定的元素?
【发布时间】:2024-01-01 11:14:01
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: jquery jquery-ui datepicker clone


    【解决方案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'});
            }
        });
    });
    

    【讨论】: