如何在不删除子元素的情况下删除包装器(父元素)?

29

我想删除父元素而不删除子元素 - 这可能吗?

HTML结构:

<div class="wrapper">
  <img src"">
</div>
<div class="button">Remove wrapper</div>

点击按钮后,我希望得到:

<img src"">
<div class="button">Remove wrapper</div>

你可能会失去附加在子元素上的事件监听器,但是可以这样做。 - Joe Simmons
7个回答

61

我认为纯JS(ES2015)方案比jQuery方案更易读。

node.replaceWith(...node.childNodes)

Node必须是一个ElementNode

const wrapperNode = document.querySelector('h1')
wrapperNode.replaceWith(...wrapperNode.childNodes)
<h1>
  <a>1</a>
  <b>2</b>
  <em>3</em>
</h1>


4
使用 TypeScript: node.replaceWith(...Array.from(node.children)); };``` 翻译:这段代码定义了一个名为 "unwrap" 的函数,它接受一个 "Element" 类型的参数 "node"。该函数将 "node" 元素的所有子元素替换为自身,并返回新的子节点数组。 - Shnigi
保留子事件监听器和简单解决方案。 - di3

34

不使用 innerHTML 的纯JS解决方案:

function unwrap(wrapper) {
    // place childNodes in document fragment
    var docFrag = document.createDocumentFragment();
    while (wrapper.firstChild) {
        var child = wrapper.removeChild(wrapper.firstChild);
        docFrag.appendChild(child);
    }

    // replace wrapper with document fragment
    wrapper.parentNode.replaceChild(docFrag, wrapper);
}

试一试:

unwrap(document.querySelector('.wrapper'));

1
避免使用 innerHTML 有什么好处? - ajbeaven
12
保留现有的DOM对象(而不是使用innerHTML重新创建它们),意味着与它们相关联的任何事件监听器都会被保留。 - HeyHeyJC
2
不错的解决方案,但是没有必要从包装器中删除子元素,因为docFrag.appendChild(wrapper.firstChild);会自动将节点从当前位置移动到新位置。在MDN上阅读更多关于appendChild的内容 - Robbendebiene

21

很惊讶没有人发布最简单的答案:

// Find your wrapper HTMLElement
var wrapper = document.querySelector('.wrapper');

// Replace the whole wrapper with its own contents
wrapper.outerHTML = wrapper.innerHTML;

4
即使你失去听众,这也是有趣的。 - bormat

11

1
应该是 $('.wrapper img').unwrap() 吗? - Kai
2
如果有更多的内容,则返回翻译后的文本:+1,否则返回 $('.wrapper').children().unwrap(); - PSL
1
谢谢Yo!:)您的+1被优雅地接受了,为OP提供更多的内容,干杯! - Tats_innit
如果有 +1,以及如果(有时)只有文本内容(即没有子元素),则 $('.wrapper').contents().unwrap(); - Andrew Cheong

6

纯JavaScript解决方案,我相信有人可以进一步简化它,但这是一种纯JavaScript的选择。

HTML

<div class="button" onclick="unwrap(this)">Remove wrapper</div>

Javascript(纯净版)

function unwrap(i) {
    var wrapper = i.parentNode.getElementsByClassName('wrapper')[0];
    // return if wrapper already been unwrapped
    if (typeof wrapper === 'undefined') return false;
    // remmove the wrapper from img
    i.parentNode.innerHTML = wrapper.innerHTML + i.outerHTML;
    return true;
}

JSFIDDLE


1
请检查您的工作fiddle,在解包后出现了一些问题。请修复它。 - Tushar Gupta - curioustushar
使用 innerHTML 是不好的,它会删除 HTML 中所有的事件。 - dude
@julmot 明显地...(: 如果你想要一个可以实现这个功能的解决方案,请向上或向下滚动,你会找到它。我不是在这里创建重复的答案,特别是当问题没有要求保留事件处理程序时。 (; - Jay Harris

1
如果您正在使用jQuery:

$(".wrapper").replaceWith($(".wrapper").html());

-2
如果包装元素包含文本,则文本将保留在子节点中。

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