DOM操作中,插入元素的操作是使用较多的,一般我们都会使用appendChild来做,但是使用起来很不方便,特别是涉及到表格操作:

const emptyRow = document.querySelector('tr');

const firstCol = document.createElement('td');
firstCol.className = 'first-col';
firstCol.textContent = 'first col';
emptyRow.appendChild(firstCol);

const secondCol = document.createElement('td');
secondCol.className = 'second-col';
secondCol.textContent = 'second col';
emptyRow.appendChild(secondCol);
// ...

当然上面只是一个例子,以前使用jQuery也能够极大的简化上述工作,而且现在的主流框架也为我们规避了大量的DOM操作。但实际上使用原生的DOM API也能够做到:

insertAdjacentHTML

insertAdjacentHTML能够解析字符串成为Element,并将其插入DOM树的特定位置(由position指定)。

我们可以使用insertAdjacentHTML来重写上面的例子:

const emptyRow = document.querySelector('tr');

emptyRow.insertAdjacentHTML('beforeend', `
  <td class="first-col">first col</td>
  <td class="second-col">second col</td>
`);

语法

element.insertAdjacentHTML(position, text);

position的取值和解释

<!-- beforebegin -->
<p>
  <!-- afterbegin -->
  foo
  <!-- beforeend -->
</p>
<!-- afterend -->

更多信息查看MDN

可以看到,insertAdjacentHTML不仅能够实现插入元素的功能,还能够灵活控制相对于调用元素的插入位置。

不能用于动态插入 <script> 标签的场景,根据 html5 规范,通过 innerHTML 的方式插入的 <script> 标签不会被执行。而 insertAdjacentHTMLinnerHTML 的本质上是相同的。

insertAdjacentElement

上文提到insertAdjacentHTML会先对传入的字符串进行解析转换为Element再进行插入,而其胞弟insertAdjacentElement相当于省略了解析转换的步骤,因为其直接操作的对象就是Element:

targetElement.insertAdjacentElement(position, element);

postion参数及含义和insertAdjacentHTML一样:

const emptyRow = document.querySelector('tr');

const firstCol = document.createElement('td');
firstCol.className = 'first-col';
firstCol.textContent = 'first col';
emptyRow.insertAdjacentElement('beforeend', firstCol);

当然了,如果是像上面一样需要先创建Element再进行插入操作,比appendChild还不方便,只是胜在能够控制插入位置而已。但当其处理已存在的Element时有其独到之处:处理已存在Element时,是移动的过程,并非是复制后插入的过程

<div>
    <a id="baidu" href="https://baidu.com">百度</a>
</div>
<div>
    <a id="netease" href="https://163.com">网易</a>
</div>

如果我们想要将“网易”的链接移动到“百度”链接后面,可以这样做:

const neteaseHref = document.getElementById('netease');
const baiduHref = document.getElementById('baidu');
baiduHref.insertAdjacentElement('afterend', neteaseHref);

处理完成后,DOM树将变成:

<div>
    <a id="baidu" href="https://baidu.com">百度</a>
    <a id="netease" href="https://163.com">网易</a>
</div>
<div>
</div>

insertAdjacentText

insertAdjacent*家族还有个专门用来插入文本的的成员:insertAdjacentText,其API和insertAdjacentHTML类似:

element.insertAdjacentHTML(position, text);

但它不会像insertAdjacentHTML那样对传入的text进行解析,即使传入的是DOM标签也只会作为文本渲染:

<div>
    <a id="netease" href="https://163.com">网易</a>
</div>
const neteaseHref = document.getElementById('netease');
neteaseHref.insertAdjacentText('beforebegin', '<span class="highlight">163</span>');

处理完成后DOM树会变为:

<div>
  "<span class="highlight">163</span>"
  <a id="netease" href="https://163.com">网易</a>
</div>

注意,渲染出来的是文本,而不是一个span元素。

总结

使用insertAdjacent*能够方便地进行插入、移动、修改textContent等DOM操作,特别是能够指定操作的相对位置能够避免大量的查找工作。

指定插入位置时要注意,beforebeginafterend两个选项,只有当操作元素拥有父级元素时才能正常工作。