jQuery 每个结合 replaceWith 问题
jQuery each combined with replaceWith issue
我试图用 class 遍历每个元素,然后用 div 包裹它,然后继续下一个。
目前正在使用这个...
$('.img-editable').each(function(i) {
if ($(this).prop("tagName") == "IMG") {
$(this).replaceWith('<span class="img-edit-container">'+this.outerHTML+'<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
} else {
$(this).replaceWith('<span class="img-edit-container bg-img-edit-container">'+this.outerHTML+'<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
}
});
它适用于简单的情况。但挑战是当有这样的嵌套元素时...
<div class="img-editable>
<div id="something else">
<div class="img-editable"></div>
</div>
</div>
然后它分崩离析,内部元素没有正确包装。
我相信 each()
函数正在循环最外层的元素,当它匹配第一个元素时,它会执行 replaceWith()
然后继续。但是当循环到达下一个(内部)时,对匹配的第二个内部元素的引用不再存在(根据浏览器)。
我也试过这个...
var setupImgWrapper = function(elem) {
if (elem.prop("tagName") == "IMG") {
elem.replaceWith('<span class="img-edit-container">'+this.outerHTML+'<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
elem.children('.img-edtiable').each(function(i) {
setupImgWrapper($(this));
});
} else {
elem.replaceWith('<span class="img-edit-container bg-img-edit-container">'+this.outerHTML+'<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
elem.children('.img-edtiable').each(function(i) {
setupImgWrapper($(this));
});
}
}
$('.img-editable').each(function(i) {
setupImgWrapper($(this));
});
这完全失败了。
我很想知道我们如何克服这个问题?在执行 replaceWith()
之后,有没有办法维护 DOM 引用,或者我们可以更新它?
TL;DR 在选定元素上执行 replaceWith
循环后,后代元素引用似乎中断并且这些元素未成功更新。
谢谢!
下面接受的解决方案
$('.img-editable').each(function(i) {
if ($(this).prop("tagName") == "IMG") {
$(this).wrap('<span class="img-edit-container"></span>');
$(this).after('<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>');
} else {
$(this).wrap('<span class="img-edit-container bg-img-edit-container"></span>');
$(this).after('<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>');
}
});
jQuery 提供了一个 .wrap() 方法,它可以满足您的需求。
这是一个演示
$('body > div').each(function() {
$(this).wrap('<div class="wrapper" />');
});
.wrapper {
border: 1px solid tomato;
margin-bottom: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Normal Element</div>
<div>
<span>Simple inline element</span>
</div>
<div>
<div>
<h1>More Stuff</h1>
</div>
</div>
如果 .img-editable > ... > .img-editable
破坏了您的代码,您应该更喜欢更适合您需要的选择器。我可以为您提供帮助,只需 post 对此答案发表评论,我们就会解决问题。 :)
试试 wrapall api 和 each
$( ".img-editable" ).wrapAll( "<span class='img-edit-container'/>");
$(".img-edit-container .img-editable").each( function(){
if ( $( this ).prop("tagName") == "IMG" )
{
$(this).parent().append ( '<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>' );
}
else
{
$(this).parent().append ( '<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>' );
}
});
甚至更简单
$( ".img-editable" ).wrapAll( "<span class='img-edit-container'/>");
$(".img-edit-container").append( '<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>' );
$(".img-edit-container img.img-editable").siblings( "button" ).toggleClass( "btn-sm" ).toggleClass( "bg-img-edit" );
我试图用 class 遍历每个元素,然后用 div 包裹它,然后继续下一个。
目前正在使用这个...
$('.img-editable').each(function(i) {
if ($(this).prop("tagName") == "IMG") {
$(this).replaceWith('<span class="img-edit-container">'+this.outerHTML+'<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
} else {
$(this).replaceWith('<span class="img-edit-container bg-img-edit-container">'+this.outerHTML+'<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
}
});
它适用于简单的情况。但挑战是当有这样的嵌套元素时...
<div class="img-editable>
<div id="something else">
<div class="img-editable"></div>
</div>
</div>
然后它分崩离析,内部元素没有正确包装。
我相信 each()
函数正在循环最外层的元素,当它匹配第一个元素时,它会执行 replaceWith()
然后继续。但是当循环到达下一个(内部)时,对匹配的第二个内部元素的引用不再存在(根据浏览器)。
我也试过这个...
var setupImgWrapper = function(elem) {
if (elem.prop("tagName") == "IMG") {
elem.replaceWith('<span class="img-edit-container">'+this.outerHTML+'<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
elem.children('.img-edtiable').each(function(i) {
setupImgWrapper($(this));
});
} else {
elem.replaceWith('<span class="img-edit-container bg-img-edit-container">'+this.outerHTML+'<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button></span>');
elem.children('.img-edtiable').each(function(i) {
setupImgWrapper($(this));
});
}
}
$('.img-editable').each(function(i) {
setupImgWrapper($(this));
});
这完全失败了。
我很想知道我们如何克服这个问题?在执行 replaceWith()
之后,有没有办法维护 DOM 引用,或者我们可以更新它?
TL;DR 在选定元素上执行 replaceWith
循环后,后代元素引用似乎中断并且这些元素未成功更新。
谢谢!
下面接受的解决方案
$('.img-editable').each(function(i) {
if ($(this).prop("tagName") == "IMG") {
$(this).wrap('<span class="img-edit-container"></span>');
$(this).after('<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>');
} else {
$(this).wrap('<span class="img-edit-container bg-img-edit-container"></span>');
$(this).after('<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>');
}
});
jQuery 提供了一个 .wrap() 方法,它可以满足您的需求。
这是一个演示
$('body > div').each(function() {
$(this).wrap('<div class="wrapper" />');
});
.wrapper {
border: 1px solid tomato;
margin-bottom: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Normal Element</div>
<div>
<span>Simple inline element</span>
</div>
<div>
<div>
<h1>More Stuff</h1>
</div>
</div>
如果 .img-editable > ... > .img-editable
破坏了您的代码,您应该更喜欢更适合您需要的选择器。我可以为您提供帮助,只需 post 对此答案发表评论,我们就会解决问题。 :)
试试 wrapall api 和 each
$( ".img-editable" ).wrapAll( "<span class='img-edit-container'/>");
$(".img-edit-container .img-editable").each( function(){
if ( $( this ).prop("tagName") == "IMG" )
{
$(this).parent().append ( '<button class="btn btn-default btn-sm img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>' );
}
else
{
$(this).parent().append ( '<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>' );
}
});
甚至更简单
$( ".img-editable" ).wrapAll( "<span class='img-edit-container'/>");
$(".img-edit-container").append( '<button class="btn btn-default bg-img-edit img-edit popover-trigger"><i class="fa fa-file-image-o"></i></button>' );
$(".img-edit-container img.img-editable").siblings( "button" ).toggleClass( "btn-sm" ).toggleClass( "bg-img-edit" );