更有效/合适的方式来编写此DOM操作?

时间:2019-04-16 06:34:30

标签: javascript html

我是Vanilla JavaScript的初学者,只是在下面编写了用于更改HTML的代码。 它可以工作,但是我想知道是否有更有效/合适的方法。 预先感谢您的帮助。

HTML 之前

<section id="anchor-a">
<p>lorem ipsum....</p>
</section>
<section id="anchor-b">
<p>lorem ipsum....</p>
</section>

HTML 之后

<section>
<div id="anchor-a" class="anchor"></div>
<p>lorem ipsum....</p>
</section>
<section>
<div id="anchor-b" class="anchor"></div>
<p>lorem ipsum....</p>
</section>

我的JavaScript代码

const anchor = document.querySelectorAll('[id^="anchor-"]');
anchor.forEach((element) => {
  let newDiv = document.createElement('div');
  newDiv.classList.add('anchor');
  newDiv.setAttribute('id', element.getAttribute("id"));
  ;
  element.insertBefore(newDiv, element.firstChild);
  element.removeAttribute('id');
});

2 个答案:

答案 0 :(得分:3)

更简洁的版本是insertAdjacentHTML,它可能更易于阅读:

const anchor = document.querySelectorAll('[id^="anchor-"]');
anchor.forEach((section) => {
  section.insertAdjacentHTML('afterbegin', `<div id="${section.id}">`);
  section.removeAttribute('id');
});
// next line is not needed, just cleans up the console output for demonstration
document.currentScript.remove();
console.log(document.body.innerHTML);
<section id="anchor-a">
<p>lorem ipsum....</p>
</section>
<section id="anchor-b">
<p>lorem ipsum....</p>
</section>

还要注意,querySelectorAll返回一个NodeList,只有较新的浏览器才具有NodeList.prototype.forEach功能。对于较旧的浏览器和IE,要么包含polyfill,要么改为使用Array.prototype.forEach.call

Array.prototype.forEach.call(
  document.querySelectorAll('[id^="anchor-"]'),
  (section) => {
    section.insertAdjacentHTML('afterbegin', `<div id="${section.id}">`);
    section.removeAttribute('id');
  }
);
// next line is not needed, just cleans up the console output for demonstration
document.currentScript.remove();
console.log(document.body.innerHTML);
<section id="anchor-a">
<p>lorem ipsum....</p>
</section>
<section id="anchor-b">
<p>lorem ipsum....</p>
</section>

(当然,如果使用ES6 +语法,如果要支持古代浏览器,请记住除了polyfill之外,还应向下移植到ES5)

答案 1 :(得分:0)

将这个问题放在性能上,在一个循环中操作DOM是一个坏主意。 DOM交互是昂贵的操作,建议始终循环执行操作。

我建议的是:

  • 找到要执行搜索的父元素。
  • 对其进行克隆。
  • 对元素执行操作。由于您正在研究克隆,因此您无需在DOM上进行任何更改。任何完成的操作都仅在内存中。
  • 现在删除此容器元素并将已处理的克隆添加到父元素。

var container = document.querySelector('.container');
var copy = container.cloneNode(true);
const anchor = copy.querySelectorAll('[id^="anchor-"]');

anchor.forEach((element) => {
  let newDiv = document.createElement('div');
  newDiv.classList.add('anchor');
  newDiv.setAttribute('id', element.getAttribute("id"));;
  element.insertBefore(newDiv, element.firstChild);
  element.removeAttribute('id');
});

container.insertAdjacentElement('afterend', copy)
container.remove();
<div class='container'>
  <section id="anchor-a">
    <p>lorem ipsum....</p>
  </section>
  <section id="anchor-b">
    <p>lorem ipsum....</p>
  </section>
</div>

注意:不更改与元素处理有关的任何代码关系作为CertainPerformance的地址

有趣的读物: