为什么将类从classList中删除,而不是从目标事件本身中删除?

问题描述

我有一个动态生成的段落列表,每个段落都有一个svg用作同步图标(fontawesome)作为子元素。当用户单击图标时,将添加fa-spin类,导致图标旋转。在经过setTimeout()下面模拟的一些异步代码之后,我想删除添加fa-spin类,以便在下次单击图标时再次添加它。问题是event.target.classList.remove('fa-spin');无法正常工作。通过运行一些console.log()调用,我可以看到classList确实删除了该类,甚至该元素也显示为不再具有该类,但是,如果我选中“ Elements 开发工具的em>“选项卡以及UI本身,svg仍然具有该类,因此图标一直在旋转。

请注意,toggle()不是我要寻找的行为,因为单击该类应该总是再次添加该类。

HTML

  <div id="version-control-tms">
    <div id="version-control-repos">
      <h2>Version control repos</h2>
    </div>
    <div id="tms-projects">
      <h2>TMS projects</h2>
    </div>
  </div>

Paragraph.js

export default class Paragraph {

  constructor(items,placement) {

    this.items = items;
    this.placement = placement;

}

  create() {

    this.items.forEach((item,index) => {
        const paragraph = document.createElement('p');
        let placeInUI = document.querySelector(this.placement);
        paragraph.setAttribute('class','resource');
        paragraph.textContent = item.name;
        placeInUI.appendChild(paragraph);
        this.implementUpdateIcon(index);
    });
  }

implementUpdateIcon (item) {

  const resource = document.getElementsByClassName('resource')[item];
  const child = document.createElement('spam');
  child.setAttribute('class','fas fa-sync-alt');
  resource.append(child);
}

}

main.js

  document.getElementById('version-control-tms').addEventListener('click',event => {

      if (event.target.classList.contains('fa-sync-alt')) {
    
        event.target.classList.add('fa-spin');

        // Run some asynchronous code...
        setTimeout(() => {
          event.target.classList.remove('fa-spin');
        },3000);

      }

    },false);

添加课程后控制台输出

DOMTokenList(4) ["svg-inline--fa","fa-sync-alt","fa-w-16","fa-spin",value: "svg-inline--fa fa-sync-alt fa-w-16 fa-spin"]

删除类后的控制台输出

DOMTokenList(3) ["svg-inline--fa",value: "svg-inline--fa fa-sync-alt fa-w-16"]

DOM中的元素

<svg class="svg-inline--fa fa-sync-alt fa-w-16 fa-spin" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sync-alt" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" data-fa-i2svg=""></svg>

解决方法

我测试了您的代码,它似乎可以工作。您可以测试代码段:

class Paragraph {

  constructor(items,placement) {

    this.items = items;
    this.placement = placement;

}

  create() {

    this.items.forEach((item) => {
        const paragraphElem = document.createElement('p');
        let placeInUI = document.querySelector(this.placement);
        paragraphElem.classList.add('resource');
        paragraphElem.textContent = item.name;
        placeInUI.appendChild(paragraphElem);
        this.implementUpdateIcon(paragraphElem);
    });
  }

  implementUpdateIcon(paragraphElem) {
      let spanElem = document.createElement('span');
      spanElem.innerHTML = "click me!";
      spanElem.classList.add('fas','fa-sync-alt');
      paragraphElem.append(spanElem);
  }
}

window.onload = function() {
    let x = new Paragraph([{name: 'hello world!'},{name: 'hello world!'},{name: 'hello world!'}],'#tms-projects');
    x.create();
    
    document.getElementById('version-control-tms').addEventListener('click',event => {

      if (event.target.classList.contains('fa-sync-alt')) {
    
        event.target.classList.add('fa-spin');

        // Run some asynchronous code...
        setTimeout(() => {
          event.target.classList.remove('fa-spin');
        },3000);

      }

    },false);

}
span {
  display: inline-block;
  background-color: red;
}

.fa-spin {
  animation: spin 1s linear infinite;
}

@keyframes spin {
    from {transform:rotate(0deg);}
    to {transform:rotate(360deg);}
}
 <div id="version-control-tms">
    <div id="version-control-repos">
      <h2>Version control repos</h2>
    </div>
    <div id="tms-projects">
      <h2>TMS projects</h2>
    </div>
  </div>

所以问题似乎出在其他地方。

我注意到的内容(在代码段中已经更改):

  • document.createElement('spam')应该是document.createElement('span')
  • 可以使用
  • child.classList.add('fas','fa-sync-alt')代替child.setAttribute('class','fas fa-sync-alt')paragraph.setAttribute('class','resource')相同。但是请记住,IE和Opera Mini无法像这样处理多个类。也许两次classList.add是更好的解决方案。
  • 您可以将段落元素直接传递给`implementUpdateIcon'函数,并且不需要索引:
    implementUpdateIcon (paragraphElem) {
       let spanElem = document.createElement('span');
       spanElem.classList.add('fas','fa-sync-alt');
       paragraphElem.append(child);
    }