假设我有:
<body>
<div class="root">
<div class="text1"></div>
<div class="text2"></div>
</div>
</body>
并想在
text2
之后插入一些HTML。var targetHandle = document.querySelector('.root')
targetHandle.insertAdjacentHTML( 'beforeEnd', `
<div class="text3"></div>
`);
我们可以通过两种方式处理该问题:
var targetHandle = document.querySelector('.root')
var newNode1 = targetHandle.lastElementChild
var newNode2 = document.querySelector('.root > .text3')
到目前为止,一切都很好。但是,如果
insertAdjacentHTML
的内容很大并且包含许多节点:var targetHandle = document.querySelector('.root')
targetHandle.insertAdjacentHTML( 'beforeEnd', `
<div class="text3"></div>
<div class="text4"></div>
<div class="text5"></div>
`);
使用
document.querySelector
成为查找每个顶级节点的真正负担,并且lastElementChild
选择器将仅指向要注入的最后一个元素。您可能会说,这太愚蠢了,只需将这些DOM节点与父对象包装在一起,以便您可以查询和遍历:
var targetHandle = document.querySelector('.root')
targetHandle.insertAdjacentHTML( 'beforeEnd', `
<div class="parentToTheRescue">
<div class="text3"></div>
<div class="text4"></div>
<div class="text5"></div>
</div>
`);
尽管这是找到这些节点的有效方法,但我们通过创建HTML作为获取它们的方法对我们的解决方案做出了妥协。
我真正想要的是一种为每个顶级节点的句柄注入
insertAdjacentHTML
的方法,但又不需要使用父包装器:var nodeList = [ ... ]
我有几个想法,到目前为止我还不为之疯狂,因为我担心性能问题:
无论如何都要使用父包装器。插入后,将获取子节点的句柄。复制/粘贴子级到父级,删除父级。
为要粘贴到的树中的现有节点拍摄快照。插入后,拍摄另一个快照并进行差异查找新节点。
寻找其他想法!谢谢
最佳答案
Convert your markup to a DocumentFragment,
从那里查询您的Elements,
仅在将DocumentFragment插入文档中之后,才存在其内容。
const targetHandle = document.querySelector('.root');
const markup = `
<div class="text3"></div>
<div class="text4"></div>
<div class="text5"></div>
`;
const elems = getInsertedElementsFromMarkup( targetHandle, markup, 'beforeend' );
elems.forEach( (elem) => {
elem.textContent = 'I just got inserted in the doc';
});
function getInsertedElementsFromMarkup( target, markup, position = "beforeend" ) {
if( !(target instanceof Node) ) {
throw new TypeError( 'Argument 1 is not a Node' );
}
if( typeof markup !== "string" ) {
throw new TypeError( 'Argument 2 is not a DOMString' );
}
// Convert our markup to a DocumentFragment
const frag = target.ownerDocument.createRange()
.createContextualFragment( markup );
// Convert to Array,
// DocumentFragments don't support `:scope` and HTMLCollection is live...
const elems = [... frag.children];
switch ( position ) {
case 'beforebegin':
target.parentNode.insertBefore( frag, target );
break;
case 'afterbegin':
target.insertBefore( frag, target.firstChild );
break;
case 'afterend':
target.parentNode.insertBefore( frag, target.nextSibling );
break;
default: // "beforeend"
target.appendChild( frag );
}
// return our queried nodes, once they are in the doc
return elems;
}
.root>div {
border: 1px solid;
height: 18px;
margin: 6px 0;
}
<div class="root">
<div class="text1"></div>
<div class="text2"></div>
</div>