假设我有:
<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 = [ ... ]
结合我的想法,到目前为止我还不疯狂,因为我担心性能问题:
始终使用父包装器。插入后,将获取子节点的句柄。将孩子复制/粘贴到父母级别,删除父母。
为要粘贴到的树中的现有节点拍摄快照。插入后,拍摄另一个快照并进行比较以找到新的节点。
正在寻找其他想法!谢谢
答案 0 :(得分:2)
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>