jQuery克隆重复的ID问题

53

我有一个包含大量无序列表的HTML元素。我需要克隆这个元素并将其放置在页面的其他位置,并添加不同的样式(使用jQuery很简单)。

$("#MainConfig").clone(false).appendTo($("#smallConfig"));

然而问题在于所有列表及其相关的列表项都有ID,而clone会复制它们。在使用jQuery进行附加之前,是否有一种简单的方法可以替换所有这些重复的ID?

9个回答

44
如果您需要在克隆列表项后引用它们,必须使用类而不是ID。将所有id="..."更改为class="..."。
如果您正在处理传统代码或某些内容,无法将ID更改为类,则必须在附加之前删除ID属性。
$("#MainConfig").clone(false).find("*").removeAttr("id").appendTo($("#smallConfig"));

只要注意,现在你没有办法再引用单个的项了。


1
类似的效果没有通过替换ID实现吗? - Sheff
1
然后,您必须跟踪 id 如何更改(即前缀、后缀),并使用字符串连接来重新构建正确的 id,以便在引用克隆元素时使用。很烦人。只需使用类即可。 - Crescent Fresh
克隆并更改id:“https://dev59.com/BWkw5IYBdhLWcg3wHW7n” - Darius Miliauskas

19

由于OP要求在追加元素之前替换重复的id,也许以下方法可以解决问题。假设您想要在这样一个HTML块中克隆MainConfig_1:

<div id="smallConfig">
    <div id="MainConfig_1">
        <ul>
            <li id="red_1">red</li>
            <li id="blue_1">blue</li>
        </ul>
    </div>
</div>

以下是可能的代码示例,用于查找所有克隆块的子元素(和后代),并使用计数器修改它们的id:

var cur_num = 1;    // Counter used previously.
//...
var cloned = $("#MainConfig_" + cur_num).clone(true, true).get(0);
++cur_num;
cloned.id = "MainConfig_" + cur_num;                  // Change the div itself.
$(cloned).find("*").each(function(index, element) {   // And all inner elements.
    if(element.id)
    {
        var matches = element.id.match(/(.+)_\d+/);
        if(matches && matches.length >= 2)            // Captures start at [1].
            element.id = matches[1] + "_" + cur_num;
    }
});
$(cloned).appendTo($("#smallConfig"));

要创建像这样的新HTML:

<div id="smallConfig">
    <div id="MainConfig_1">
        <ul>
            <li id="red_1">red</li>
            <li id="blue_1">blue</li>
        </ul>
    </div>
    <div id="MainConfig_2">
        <ul>
            <li id="red_2">red</li>
            <li id="blue_2">blue</li>
        </ul>
    </div>
</div>

16
$("#MainConfig")
    .clone(false)
    .find("ul,li")
    .removeAttr("id")
    .appendTo($("#smallConfig"));

试试这个。 :)

[编辑] 根据redsquare的评论进行了修正。


在运行append之前,我会删除id,否则你会在dom中复制id,这可能会产生不良影响。 - redsquare
这基本上是Salty在他的示例中所做的,我想。我会尝试一下,但我宁愿使用全局查找来查找所有子元素,以防标记更改并且父元素内的其他元素被复制。 - Sheff
2
谢谢,这非常有用,因为我可以使用$('#itemBase').clone(true).removeAttr('id').attr('id','item'+nextItemId++).removeClass('hidden').addClass('item').insertAfter($('#itemBase')); - dlamblin

6
我使用类似以下代码的方法: $("#details").clone().attr('id','details_clone').after("h1").show();

3
哦,这甚至更短:var i=$('#itemBase'); i.clone(true).attr('id','item'+nextItemId++) .removeClass('hidden').addClass('item').insertAfter(i);该代码意为:选择一个id为"itemBase"的元素,复制它并将新元素的id设为"item"+nextItemId,nextItemId是一个自增的变量。然后移除新元素中的 "hidden" 类,并添加 "item" 类。最后将新元素插入到原始元素之后。 - dlamblin

4
这是基于Russell的答案,但在表单方面更美观和实用。 jQuery:
$(document).ready(function(){
   var cur_num = 1;    // Counter

    $('#btnClone').click(function(){

          var whatToClone = $("#MainConfig"); 
          var whereToPutIt = $("#smallConfig");

          var cloned = whatToClone.clone(true, true).get(0);
          ++cur_num;
          cloned.id = whatToClone.attr('id') + "_" + cur_num;                  // Change the div itself.

        $(cloned).find("*").each(function(index, element) {   // And all inner elements.
          if(element.id)
          {
              var matches = element.id.match(/(.+)_\d+/);
              if(matches && matches.length >= 2)            // Captures start at [1].
                  element.id = matches[1] + "_" + cur_num;
          }
          if(element.name)
          {
              var matches = element.name.match(/(.+)_\d+/);
              if(matches && matches.length >= 2)            // Captures start at [1].
                  element.name = matches[1] + "_" + cur_num;
          }

         });

       $(cloned).appendTo( whereToPutIt );

    });
});

标记语言:

<div id="smallConfig">
    <div id="MainConfig">
        <ul>
            <li id="red_1">red</li>
            <li id="blue_1">blue</li>
        </ul>
      <input id="purple" type="text" value="I'm a text box" name="textboxIsaid_1" />
    </div>
</div>

3

顺便提一下,我使用了Dario的函数,但还需要捕获表单标签。

添加另一个if语句以实现这个功能:

if(element.htmlFor){
var matches = element.htmlFor.match(/(.+)_\d+/);
if(matches && matches.length >= 2)            // Captures start at [1].
  element.htmlFor = matches[1] + "_" + cur_num;
}

0

我相信这是最好的方法

var $clone = $("#MainConfig").clone(false);
$clone.removeAttr('id'); // remove id="MainConfig"
$clone.find('[id]').removeAttr('id'); // remove all other id attributes
$clone.appendTo($("#smallConfig")); // add to DOM.

0
如果您在页面上有几个类似的项目,最好使用类而不是ID。这样,您可以将样式应用于不同容器ID内部的UL。

0

这里是一个带有ID的解决方案。

var clone = $("#MainConfig").clone();
clone.find('[id]').each(function () { this.id = 'new_'+this.id });
$('#smallConfig').append(clone);

如果您想动态设置ID,可以使用计数器而不是'new_'。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接