问题 jQuery的after方法不使用新创建的元素


就我所知,以下代码应该可以工作,创建一个 <div> 元素,然后创建一个 <p> 元件;表达式应该导致一个带有两个元素的jQuery对象:

$("<div>first element's content</div>").after("<p>second element's content</p>");

但是,我得到的是非常不同的。 文档 (请参阅“插入断开的DOM节点”标题)告诉我上面的代码应该生成一个jQuery对象,抓取两个HTML片段并构建两个DOM元素。但是,我所获得的,在几个不同版本的jQuery中,都高于1.4,是一个只有1个节点的jQuery对象。但是,下面的代码工作正常,返回(我相信)正确的jQuery对象,里面有两个元素:

$("<div></div>").after("<p>second element's content</p>");

这个例子也适用:

$("<div></div>").after("<p>second element's content</p>").after("<p>third element's content</p>");

好像是 .after() 如果正在创建的第一个DOM节点为空,则方法可以正常工作,但如果不是,则无法工作(无论后续DOM节点的内容是否附加到该节点)。

我是否遗漏了有关jQuery的内部,奇怪的DOM问题和/或JavaScript特性的问题,或者这只是一个jQuery错误,从版本1.4到1.7继续存在?

这是一个微薄的JSFiddle 很明显地展示了这个问题。)


3460
2018-05-07 21:21


起源

正如下面评论中提到的那样 elclanrs 回答, add 是一个可行的替代品,我掀起了一个 新JSFiddle 证明它有效。但是,这并不能解释为什么显示的行为 文档 (甚至它的评论,请参阅包含“MarkAndrewSlade”答案的整个帖子) after 当该元素具有内容时,新创建的元素的jQuery对象的方法。 - Paul Sebastian Bruno


答案:


这是jQuery <1.9中的已知错误。看到 http://bugs.jquery.com/ticket/8759

在jQuery> = 1.9中, 以下来自升级指南的信息 应该注意:

在1.9之前, .after().before(),和 .replaceWith() 如果集合中的第一个节点未连接到文档,则会尝试在当前jQuery集中添加或更改节点,并且在这些情况下返回新的jQuery集而不是原始集。这会产生一些不一致和彻头彻尾的错误 - 该方法可能会也可能不会根据其参数返回新结果!从1.9开始,这些方法总是返回原始的未修改集并尝试使用 .after().before(), 要么 .replaceWith() 在没有父节点的节点上没有效果 - 也就是说,它所包含的集合或节点都没有更改。


7
2018-05-07 22:33



非常感谢, 麦克风。 - Paul Sebastian Bruno
奇怪的是,在将jQuery从1.8.2更新到1.11.0后,我遇到了同样的错误。 $ .after()和$ .before()方法不适用于新创建的元素。我需要先将新创建的元素添加到DOM中,然后将新内容插入其中。另一种解决方法是使用$ .add()方法,但如果您希望在元素之前插入内容,它将无法工作。 - Leonardo Montenegro
更新到jQuery 1.10后,我也得到了这种行为 - DrCord
我使用的是2.2.3版,但它仍然无效。在将我的头撞在墙上之后,最后检查了SO。 - JasonlPrice


使用 add() 将对象添加到集合中。我用 after() 更多在已存在或缓存在变量中的DOM元素中,但大多数情况下,如果使用动态标记,则使用等效项更实用 insertAfter()

$("<div>first element's content</div>").add("<p>second element's content</p>");

编辑:

这有效......

var $el = $('<div/>', {
    text: 'hey there'
}).after('<p>Lorem</p>');

6
2018-05-07 21:32



谢谢, elclanrs, 期待你的答复。我会用的 add 在将来。而我只是掀起了一个 新JSFiddle 证明这一点 add 做你提到的。但这并没有回答我的问题,这就是原因 after 才不是。 - Paul Sebastian Bruno
看编辑...不知道为什么这个bug但是有效。 - elclanrs
再次感谢。由于它没有回答我的问题,我没有给你回答信用,但我已经投票给你的答案,因为它在我的问题中找到了一个新的粒度。 - Paul Sebastian Bruno


我发现我有时仍然遇到问题 .add() 代替 .after(),所以解决这个错误的另一个简单方法是抛弃一个包装元素, .append() 兄弟元素,并使用 .html() 只是获取包装器的内部内容。

$('body').append(
    $('<span/>').append(
        $("<div>first element's content</div>")
    ).append(
        $("<p>second element's content</p>")
    ).html()
);

这将添加 <div> 和 <p> 但丢弃外面的 <span>。我发现这通常可以正常使用 .append() 但可能有问题 .appendTo()


0
2017-11-06 20:39





在jQuery 1.12.4中,我发现使用了一个 类选择器 而不是ID选择器解决了这个问题。

如果你正在努力
$("#myelement1").after("<p>test</p>")

为您的元素添加一个唯一的类并尝试这样:
$(".myelement1").after("<p>test</p>")


0
2018-05-18 12:54