如何使用 document.getElementsByClassName 和 Element.classList 正确切换 类

How to correctly toggle classes using document.getElementsByClassName and Element.classList

我有一个页面,我希望能够在其中打开或关闭特定元素的 classes。

为了尝试做到这一点,我编写了一个函数:

function toggleClass(obj) {
    alert(obj.className);
      Array.from(document.getElementsByClassName(obj.className)).forEach(function(element) {
        element.classList.toggle(obj.className);
    });
}

由 table 中的项目调用,例如 <td style=""><span class="determiner" onclick="toggleClass(this)">Determiner</span></td>.

当我第一次单击该项目时,它工作正常,触发警报并删除 class。当我再次单击 table 中的相同项目并尝试 toggle/add class 时,将触发警报(为空,因为 class 已被删除)但是 class 未添加。

谁能告诉我这里做错了什么?

function toggleClass(obj) {
    alert(obj.className);
      Array.from(document.getElementsByClassName(obj.className)).forEach(function(element) {
        element.classList.toggle(obj.className);
    });
}
.determiner {
  /* color: rgb(248, 8, 8); */
  border: 1px solid rgb(248, 8, 8);
}

.preposition {
  color: rgb(40, 18, 236);
  /* border: 1px solid rgb(40, 18, 236); */
}

.verb-present {
  color: rgb(13, 146, 68);
  /* border: 3px solid rgb(13, 146, 68); */
}

span[class^='noun-'], span[class*=' noun-']{
  color: #F00;
}
<table class="grammar table table-hover" data-toggle="table" data-sort-name="instance_use" data-sort-order="desc">
            <thead><tr><th style="" data-field="grammar_type" tabindex="0"><div class="th-inner sortable both">Grammar Type</div><div class="fht-cell"></div></th><th style="" data-field="instance_use" tabindex="0"><div class="th-inner sortable both desc">Instances of Use</div><div class="fht-cell"></div></th></tr></thead>
            <tbody><tr data-index="0"><td style=""><span class="adverb" onclick="toggleClass(this)">Adverb</span></td><td style="">2 </td></tr><tr data-index="1"><td style=""><span class="verb-present" onclick="toggleClass(this)">Verb, present</span></td><td style="">2 </td></tr><tr data-index="2"><td style=""><span class="determiner" onclick="toggleClass(this)">Determiner</span></td><td style="">2 </td></tr><tr data-index="3"><td style=""><span class="noun-sing-or-mass" onclick="toggleClass(this)">Noun, sing. or mass</span></td><td style="">1 </td></tr><tr data-index="4"><td style=""><span class="" onclick="toggleClass(this)">Preposition</span></td><td style="">1 </td></tr><tr data-index="5"><td style=""><span class="noun-plural" onclick="toggleClass(this)">Noun, plural</span></td><td style="">1 </td></tr><tr data-index="6"><td style=""><span class="comma" onclick="toggleClass(this)">Comma</span></td><td style="">1 </td></tr><tr data-index="7"><td style=""><span class="personal-pronoun" onclick="toggleClass(this)">Personal pronoun</span></td><td style="">1 </td></tr></tbody>
        </table>
        
<div id="story_text">
            <span style="white-space: pre-line">
            <span class="adverb">here</span> <span class="verb-present">is</span> <span class="determiner">a</span> <span class="noun-sing-or-mass">story</span> <span class="">with</span> <span class="determiner">no</span> <span class="noun-plural">commas</span><span class="comma">,</span> <span class="adverb">now</span> <span class="personal-pronoun">it</span> <span class="verb-present">does</span>
            </span>
        </div>

问题是你一直在引用 obj.className,但是在 forEach 循环中,一旦点击的元素被迭代,obj.className 就会变成空白,所以在进一步的迭代中(例如is a story中的"a"),传递给element.classList.toggle的字符串为空。

另一个问题是,当您尝试再次单击该元素时,它不存在 class,因此 obj.className 是空的 - 没有 class 可以重新打开。

与其在 HTML 属性中添加处理程序(这与 eval 一样糟糕),不如尝试先遍历所有需要处理程序的元素 ,所以你可以为每个你想要切换的 className 构建一个元素数组。

一个不太优雅的解决方案(需要更少的更改)是切换 不同的 class 覆盖 colorborder determiner 和其他 class 的属性:

function toggleClass(obj) {
  const className = obj.classList[0];
  document.querySelectorAll('.' + className).forEach(element => {
    element.classList.toggle('blank');
  });
}
.determiner {
  /* color: rgb(248, 8, 8); */
  border: 1px solid rgb(248, 8, 8);
}

.preposition {
  color: rgb(40, 18, 236);
  /* border: 1px solid rgb(40, 18, 236); */
}

.verb-present {
  color: rgb(13, 146, 68);
  /* border: 3px solid rgb(13, 146, 68); */
}

span[class^='noun-'],
span[class*=' noun-'] {
  color: #F00;
}

.blank {
  border: 0;
  color: black !important;
}
<table class="grammar table table-hover" data-toggle="table" data-sort-name="instance_use" data-sort-order="desc">
            <thead><tr><th style="" data-field="grammar_type" tabindex="0"><div class="th-inner sortable both">Grammar Type</div><div class="fht-cell"></div></th><th style="" data-field="instance_use" tabindex="0"><div class="th-inner sortable both desc">Instances of Use</div><div class="fht-cell"></div></th></tr></thead>
            <tbody><tr data-index="0"><td style=""><span class="adverb" onclick="toggleClass(this)">Adverb</span></td><td style="">2 </td></tr><tr data-index="1"><td style=""><span class="verb-present" onclick="toggleClass(this)">Verb, present</span></td><td style="">2 </td></tr><tr data-index="2"><td style=""><span class="determiner" onclick="toggleClass(this)">Determiner</span></td><td style="">2 </td></tr><tr data-index="3"><td style=""><span class="noun-sing-or-mass" onclick="toggleClass(this)">Noun, sing. or mass</span></td><td style="">1 </td></tr><tr data-index="4"><td style=""><span class="" onclick="toggleClass(this)">Preposition</span></td><td style="">1 </td></tr><tr data-index="5"><td style=""><span class="noun-plural" onclick="toggleClass(this)">Noun, plural</span></td><td style="">1 </td></tr><tr data-index="6"><td style=""><span class="comma" onclick="toggleClass(this)">Comma</span></td><td style="">1 </td></tr><tr data-index="7"><td style=""><span class="personal-pronoun" onclick="toggleClass(this)">Personal pronoun</span></td><td style="">1 </td></tr></tbody>
        </table>
        
<div id="story_text">
            <span style="white-space: pre-line">
            <span class="adverb">here</span> <span class="verb-present">is</span> <span class="determiner">a</span> <span class="noun-sing-or-mass">story</span> <span class="">with</span> <span class="determiner">no</span> <span class="noun-plural">commas</span><span class="comma">,</span> <span class="adverb">now</span> <span class="personal-pronoun">it</span> <span class="verb-present">does</span>
            </span>
        </div>