2015-07-21 61 views
3

我正在用outerHTML替换DOM元素来替换它的内容。这个技巧很有用,但我需要立即访问新创建的DOM元素。用outerHTML替换元素并立即访问新创建的元素

不幸的是,创建元素<x>和生成var code的内容不受我控制。

var code, e; 
 

 
(function() { 
 
    /** 
 
    * Things done inside this IIFE is not under my control 
 
    */ 
 
    code = 
 
    '<div style="border: 1px solid black;">' + 
 
    ' <span>I </span>' + 
 
    ' <span>want </span>' + 
 
    ' <span>to </span>' + 
 
    ' <span>access </span>' + 
 
    ' <span>all </span>' + 
 
    ' <span>these </span>' + 
 
    ' <span>spans.</span>' + 
 
    '</div>'; 
 
    e = document.getElementById('replace_this'); 
 
}()); 
 

 
e.outerHTML = code; 
 

 
// by this point, element e is replaced with newly added HTML. Let's do 
 
// an alert to make sure 
 
alert('Check the document. New HTML is rendered.'); 
 

 
var spans = e.getElementsByTagName('span'); // oops! empty collection 
 
alert(spans.length); // alerts 0 
 
alert(e.outerHTML); // alerts '<x></x>'
<div id="container" style="padding: 20px; border: 1px dashed grey;"> 
 
    <div>Don't replace this.</div> 
 
    <x id="replace_this"></x> 
 
    <div>Don't replace this either.</div> 
 
</div>

行为处于MDN's notes on outerHTML说明:

另外,虽然元素将文档,其可变的outerHTML属性设定将仍持有参考被替换原始元素

所以我的问题是,我如何在替换旧元素后立即访问新添加的元素? PS:我准备放弃outerHTML,如果还有另一种方法可以用来替换元素,然后访问新创建的元素,则可以使用outerHTML

+1

你不会能够,因为你已经有效地删除了父元素“e”。该对象仍然保留在HTML的旧副本中。您可以通过将'code'应用于'e.innerHTML'来欺骗它,然后设置'e.outerHTML = e.innerHTML',但这又是在现在不存在的节点列表中运行。我不会建议这种方法,因为它可能在不同的浏览器中有不同的功能。 –

+0

我没有任何困难使用你的代码访问它:var target = document.getElementById('container'); alert(elementChildren(target)[0] .children.length); (var i = 0; i

+0

这不是你要找的吗? –

回答

3

最后,我通过调用previousSibling,然后用parentElement.removeChild

var code, e; 
 

 
(function() { 
 
    /** 
 
    * Things done inside this IIFE is not under my control 
 
    */ 
 
    code = 
 
    '<div style="border: 1px solid black;">' + 
 
    ' <span>I </span>' + 
 
    ' <span>want </span>' + 
 
    ' <span>to </span>' + 
 
    ' <span>access </span>' + 
 
    ' <span>all </span>' + 
 
    ' <span>these </span>' + 
 
    ' <span>spans.</span>' + 
 
    '</div>'; 
 
    e = document.getElementById('replace_this'); 
 
}()); 
 

 
// insert the new element just before <x> 
 
e.insertAdjacentHTML('beforeBegin', code); 
 
// now <x>'s previousSibling should be the newly added element 
 
var new_elem = e.previousSibling; 
 
// get rid of <x> 
 
e.parentElement.removeChild(e); 
 

 
// by this point, element e is replaced with newly added HTML. Let's do 
 
// an alert to make sure 
 
alert('Check the document. New HTML is rendered.'); 
 

 
var spans = new_elem.getElementsByTagName('span'); 
 
alert(spans.length); // alerts 7 
 
alert(new_elem.outerHTML); // alerts contents of new element
<div id="container" style="padding: 20px; border: 1px dashed grey;"> 
 
    <div>Don't replace this.</div> 
 
    <x id="replace_this"></x> 
 
    <div>Don't replace this either.</div> 
 
</div>

去除不必要的元素入驻之前插入新元素 ,使用insertAdjacentHTML,得到了新的元素
0

为什么不给生成的div一个ID?然后,您可以在新元素上获取ElementById。

例如。

var code = 
    '<div id="newElement" style="border: 1px solid black;">' + 
    ' <span>I </span>' + 
    ' <span>want </span>' + 
    ' <span>to </span>' + 
    ' <span>access </span>' + 
    ' <span>all </span>' + 
    ' <span>these </span>' + 
    ' <span>spans.</span>' + 
    '</div>'; 

var e = document.createElement('x'); 
document.getElementById('container').appendChild(e); 
e.outerHTML = code; 

// by this point, element e is replaced with newly added HTML. Let's do 
// an alert to make sure 
alert('Check the document. New HTML is rendered.'); 

e = getElementById('newElement'); // reassign e to the new div 
var spans = e.getElementsByTagName('span'); 
alert(spans.length); 
alert(e.outerHTML); 
+0

感谢您的建议。不幸的是,创建元素的部分和生成要插入代码的部分不在我的控制之下。应该在问题中包含这些信息。抱歉。 – Krumia

1

我设法得到它优良使用下面的javascript:

var code = 
    '<div style="border: 1px solid black;">' + 
    ' <span>I </span>' + 
    ' <span>want </span>' + 
    ' <span>to </span>' + 
    ' <span>access </span>' + 
    ' <span>all </span>' + 
    ' <span>these </span>' + 
    ' <span>spans.</span>' + 
    '</div>'; 

var e = document.createElement('x'); 

document.getElementById('container').appendChild(e); 

e.outerHTML = code; 

var spans = e.getElementsByTagName('span'); // oops! empty collection 

这些都是我的变化:

/** 
* Return direct children elements. 
* 
* @param {HTMLElement} 
* @return {Array} 
*/ 
function elementChildren(element) { 
    var childNodes = element.childNodes, 
     children = [], 
     i = childNodes.length; 

    while (i--) { 
     if (childNodes[i].nodeType == 1) { 
      children.unshift(childNodes[i]); 
     } 
    } 

    return children; 
} 
var target = document.getElementById('container'); 
alert(elementChildren(target)[0].children.length); 

for (var i = 0; i < elementChildren(target)[0].children.length; i++) { 
    elementChildren(target)[0].children[i].style.border = '1px red solid'; 
    alert(elementChildren(target)[0].children[i].innerHTML); 
} 

<div id="container" style="padding: 20px; border: 1px dashed grey;"></div> 

这里是一个Codepen与代码,以便您可以编辑玩弄它:http://codepen.io/nicholasabrams/pen/VLGMgj

+0

感谢您的回答,但如果元素'#容器'有其他孩子以外的其他孩子'',这不会失败吗? – Krumia

+0

@Krumia如果你在OP中更新你的代码来显示一个新问题,我将尝试解决这个问题,但是我需要看到问题的演示 –

+1

(我发现[一个答案](http://stackoverflow.com/ a/31556230/1461424),我自己适合*我*,但想让你知道我在这个问题上所作的澄清)。我希望元素'#容器'拥有除''以外的其他子项(已在我的答案中更新)。所以不幸的是,你可以在[这个JSFiddle]中看到(http://jsfiddle.net/7dn1p6ex/)。此外,该元素是从我无法修改的函数返回的。很抱歉在获得答案后更改规则。 – Krumia