如何多次使用 .unwrap() 方法解包一个元素?

12
有没有一种方法可以多次使用Jquery的.unwrap()而不需要复制和粘贴?如果它可以接受一个参数或类似于.unwrap(4)的东西,那就太好了。但事实并非如此。是否有更巧妙的解决方案来实现以下操作?

$(".foo a").unwrap().unwrap().unwrap().unwrap();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="foo">
    <div>
        <ul>
            <li>
                <div>
                    <a href="#">Link 1</a>
                </div>
            </li>
        </ul>
    </div>
</li>
<li class="foo">
    <div>
        <ul>
            <li>
                <div>
                    <a href="#">Link 2</a>
                </div>
            </li>
        </ul>
    </div>
</li>
<li class="foo">
    <div>
        <ul>
            <li>
                <div>
                    <a href="#">Link 3</a>
                </div>
            </li>
        </ul>
    </div>
</li>
</ul>


1
这是为了一个项目还是出于好奇?如果是前者,并且你觉得必须要使用那么多次的unwrap,我建议可以考虑克隆/销毁该元素并将其附加到父级。 - zfrisch
5
$(".foo > div").replaceWith($(".foo a")) - Patrick Evans
for (var i = 0; i <= 3; i++) { $(".foo a").unwrap(); } - emerson.marini
无论您使用哪种方法,都应该意识到使用多个取消包装不如一次替换方法的性能好。 - charlietfl
@ShemSeger 请看帖子。Briefest能够将其缩减至,在这里。 - guest271314
5个回答

10

使用 parentsUntil 查找 foo 元素的子元素 (.foo > *),这些子元素是 foo 的祖先元素。

使用 addBack 包含匹配的元素本身。

$('.foo a').parentsUntil('.foo > *').addBack().unwrap();

Fiddle 1


如果您想要一个通用函数,它可以将对象解包n次,那么这就是它:

$.fn.unwrapN = function(n) {
  while(n--) $(this).unwrap();
  return $(this);
}

Fiddle 2


2
不错。谢谢你向我介绍了一种新的方法。在我看来,这应该是被接受的答案。 - Johan
1
请注意,这将取消锚元素的直接父级,而不是锚元素本身。也就是说,您将得到<li class="foo"><div><a> - Patrick Evans

8
你可以自己编写代码来实现这个功能:
$.fn.unwrapTimes = function(times){
    var unwrapCount = times;
    return this.each(function(){
        var $this = $(this);
        for(var i=0;i<unwrapCount;i++){
             $this.unwrap();   
        }
    });
};

fiddle

很明显,名称应该更改,但逻辑是正确的。


3
你可以直接使用times,而不是设置一个单独的变量。 - Patrick Evans
1
函数参数是局部的 - Patrick Evans
1
你刚才是在几秒钟内从零开始编写那段代码吗?我真希望我也能那么聪明... - Lei-Lonnie
3
正式变量是局部的。 - Roamer-1888
3
$.fn.unwrapTimes = function(n) {for (var a=this; n; n--) a=a.unwrap(); return a} 你好。 - Tobia
显示剩余5条评论

3

可以使用html()函数

$('.foo').html($('.foo a'));

这种方法对于一个实例来说不具有可扩展性,但对于多个实例可以使用 html(fn)

$('.foo').html(function(){
   return $(this).find('a')
});

演示


如果你有多个.foo列表项,这将无法工作。请参见更新的Fiddle - Lei-Lonnie
1
@RickHitchcock 是的,你的一行代码有点棘手.. 大量的 DOM 操作...很好奇在这些操作上进行性能测试的结果...许多 .foo 的取消包装不太可能非常高效。 - charlietfl
.html()会破坏元素。例如,如果您在a元素上有单击事件侦听器,则它们将被销毁。 - Salman A

2
为什么要把它弄得过于复杂呢?
var $wrapper = $('li.foo'),
    $keep = $wrapper.find('a'),
    $result = $wrapper.empty().append($keep);

console.log($result[0].outerHTML);

http://jsfiddle.net/k5mn0gnm/


这很好。但是如果有任何li.foo a的“uncles”,它会将它们全部删除。 - Salman A
@SalmanA 你的意思是兄弟姐妹吗?在这个语境中,叔叔是什么意思? :-) - Johan
1
是的,兄弟姐妹也是。叔叔阿姨是父母的兄弟姐妹。 - Salman A
@SalmanA 删除所有父级元素,直到出现.foo,对吗? - guest271314

1

对于单个foo元素,尝试使用.prependTo().empty()

 $(".foo a").prependTo($(".foo").empty());

$(".foo a").prependTo($(".foo").empty());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<li class="foo">
    <div>
        <ul>
            <li>
                <div>
                    <a href="#">Link</a>
                </div>
            </li>
        </ul>
    </div>
</li>


对于多个 .foo 类,尝试使用:
$(".foo a").each(function() {
  $(this).prependTo($(this).parents(".foo").empty());
});

http://jsfiddle.net/pu7Lmxfr/5/


无法处理多个列表项:在此处查看fiddle - Lei-Lonnie
@ShemSeger 只是添加了一个 .each() http://jsfiddle.net/pu7Lmxfr/4/。或许在 OP 中包含细节,要求将 js 应用于“多个列表项”? - guest271314
1
再仔细看一下,您已经用最后一个链接的副本替换了所有链接。 - Lei-Lonnie
@ShemSeger http://jsfiddle.net/pu7Lmxfr/5/; 更新了帖子,包括来自链接 jsfiddle 的 js - guest271314

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