简体   繁体   English

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

[英]Why class gets removed from classList, but not from the target event itself?

I have a list of paragraphs generated dynamically, each one with an svg for a sync icon (fontawesome) as a child element.我有一个动态生成的段落列表,每个段落都有一个同步图标(fontawesome)的 svg 作为子元素。 When the user clicks on the icon, a class of fa-spin is added causing the icon to spin.当用户点击图标时,会添加一类fa-spin导致图标旋转。 After some asynchronous code, simulated below by setTimeout() , I want to remove the newly-added fa-spin class to have it added again the next time the icon is clicked.在下面通过setTimeout()模拟的一些异步代码之后,我想删除新添加的fa-spin类,以便在下次单击图标时再次添加它。 The problem is that event.target.classList.remove('fa-spin');问题是event.target.classList.remove('fa-spin'); is not working.不管用。 By running some console.log() calls I can see that the classList indeed gets the class removed and even the element shows up as no longer having it, however, if I check it the " Elements " tab of the dev tools and the UI itself, the svg still has the class and therefore the icon keeps on spinning.通过运行一些console.log()调用,我可以看到classList确实删除了类,甚至元素显示为不再具有它,但是,如果我检查它,开发工具和 UI 的“元素”选项卡本身,svg 仍然具有该类,因此图标不断旋转。

Please note that toggle() is not the behavior I'm looking for because upon a click the class should always be added again.请注意, toggle()不是我正在寻找的行为,因为单击该类时应始终再次添加该类。

HTML 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段落.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);

Console output after adding the class添加类后的控制台输出

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"]

Console output after removing the class删除类后的控制台输出

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

Element in the DOM 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>

I tested you Code and it seems to work.我测试了你的代码,它似乎工作。 You can test the snippet:您可以测试代码段:

 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!'}, {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>

So the problem seems to be somewhere else.所以问题似乎出在其他地方。

Things I notice (already changed in the snippet):我注意到的事情(已经在片段中改变了):

  • document.createElement('spam') should be document.createElement('span') . document.createElement('spam')应该是document.createElement('span')
  • child.classList.add('fas', 'fa-sync-alt') can be used instead of child.setAttribute('class', 'fas fa-sync-alt') same with paragraph.setAttribute('class', 'resource') . child.classList.add('fas', 'fa-sync-alt')可以用来代替child.setAttribute('class', 'fas fa-sync-alt')paragraph.setAttribute('class', 'resource') But keep in mind that IE and Opera Mini can't handle multiple classes like so.但请记住,IE 和 Opera Mini 无法像这样处理多个类。 Maybe two times classList.add is a better solution.也许两次classList.add是更好的解决方案。
  • you can pass the paragraph element directly to the `implementUpdateIcon' function and don't need an index for it:您可以将段落元素直接传递给 `implementUpdateIcon' 函数,并且不需要索引:
     implementUpdateIcon (paragraphElem) { let spanElem = document.createElement('span'); spanElem.classList.add('fas', 'fa-sync-alt'); paragraphElem.append(child); }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM