【问题标题】:How to use JavaScript to Alter CSS for Multiple Elements如何使用 JavaScript 更改多个元素的 CSS
【发布时间】:2015-08-16 19:06:03
【问题描述】:

我正在尝试使用 JavaScript 在被选中后更改元素的背景颜色,并确保一次只有一个元素具有特定的背景颜色。一旦用户选择了不同的元素,我希望将之前选择的元素替换为不同的背景颜色。目前我只能通过选择每个元素来切换单个元素。我需要能够选择一个元素并应用新的背景颜色,然后让 JavaScript 将先前活动元素的背景颜色更改为不同的颜色(少点击一次)。

我正在尝试做的与现代导航栏或列表项非常相似,其中一次只有一个元素是“活动的”,并且背景颜色与同一 div、行等中的其他元素不同。

关于我的工作的注意事项我正在使用引导程序,并且不想在这个特定项目中使用 jQuery。

CSS:

<!DOCTYPE html>
<html lang="en">
    <head>
        <style>
            h4 {
                border: 1px solid black;
                border-radius: 8px;
                padding: 10px 2px 10px 2px;
                margin: 20px 20px 0px 20px;
                background-color: #F0F0F0;
                border-color: #F8F8F8;
                color: #505050;
                cursor: pointer;
            }

            .active {
                background-color: #99E6FF;
            }
        </style>
    </head>
</html>

HTML:

<div id="pTwoRowOne">
    <div class="row">
        <div class="col-md-4 row row-centered">
            <h4 id="techBio" class="test">Biology</h4>
        </div>
        <div class="col-md-4 row row-centered">
            <h4 id="techCart" class="test">Cartography</h4>
        </div>
        <div class="col-md-4 row row-centered">
            <h4 id="techChem" class="test">Chemistry</h4>
        </div>
    </div>
</div>

JavaScript:

document.getElementById("techBio").onclick=function() {
    document.getElementById("techBio").classList.toggle('active');
}

document.getElementById("techCart").onclick=function() {
    document.getElementById("techCart").classList.toggle('active');
}

document.getElementById("techChem").onclick=function() {
    document.getElementById("techChem").classList.toggle('active');
}

可以在这里看到一个例子:http://jsbin.com/fugogarove/1/edit?html,css,js,output

如果需要澄清,请告诉我。

【问题讨论】:

    标签: javascript css twitter-bootstrap dom


    【解决方案1】:

    是的,非常简单。

    假设

    1. 您不是在尝试支持 IE8,因为您使用的是classList
    2. 您可以将元素作为变量保存,而不是重复查询 DOM。

    示例

    JSBin

    代码

    我重写了你的 JavaScript 以使它更干净一点,并稍微干燥一下:

    var techs = [].slice.call(document.querySelectorAll('#pTwoRowOne h4'));
    
    function set_active(event) {
      techs.forEach(function(tech){
        if (event.target == tech) { return; }
        tech.classList.remove('active');
      });
      event.target.classList.toggle('active');
    }
    
    techs.forEach(function(item) {
      item.addEventListener('click', set_active);
    });
    

    一些解释

    [].slice.call(document.querySelectorAll('#pTwoRowOne h4')); – 我们使用它来将输出从 NodeList 更改为 Array。这允许我们稍后使用forEachquerySelectorAll 返回一个 NodeList,其中包含与 CSS 选择器匹配的所有元素。根据您的环境,您可能可以用更好的 CSS 选择器替换它。

    addEventListener 是一种比通过onclick += 迭代添加绑定事件监听器更好的方法。这也是 ECMA5 及更高版本中推荐的方式(据我所知)。

    通过将元素查询设置为变量,您将能够将引用保存在内存中,而不是每次都轮询 DOM 来更改元素。这将使您的 JavaScript 稍微快一些,并且它再次成为它生成的代码的更好、更简洁的版本。

    更新

    我重新设计了 JS 以使其更有意义。

    【讨论】:

    【解决方案2】:

    假设您只有一个活动元素,您可以使用 document.querySelector() 找到它 - 如果您有多个,您可以使用 document.querySelectorAll() 并遍历它们。

    简单案例:

    function activate(event) {
      var active=document.querySelector('.active');
    
      // activate the clicked element (even if it was already active)
      event.target.classList.add('active');
    
      // deactivate the previously-active element (even if it was the clicked one => toggle)
      if (active) active.classList.remove('active');
    }
    
    document.getElementById("techBio").addEventListener("click",activate);
    document.getElementById("techCart").addEventListener("click",activate);
    document.getElementById("techChem").addEventListener("click",activate);
    h4 {
       border: 1px solid black;
       border-radius: 8px;
       padding: 10px 2px 10px 2px;
       margin: 20px 20px 0px 20px;
       background-color: #F0F0F0;
       border-color: #F8F8F8;
       color: #505050;
       cursor: pointer;
    }
    	
    .active {
       background-color: #99E6FF;
    }
    <div id="pTwoRowOne">
      <div class="row">
        <div class="col-md-4 row row-centered">
          <h4 id="techBio" class="test">Biology</h4>
        </div>
        <div class="col-md-4 row row-centered">
          <h4 id="techCart" class="test">Cartography</h4>
        </div>
        <div class="col-md-4 row row-centered">
          <h4 id="techChem" class="test">Chemistry</h4>
        </div>
      </div>
    </div>

    【讨论】:

    • 我更喜欢你的 JavaScript。 :(
    • 很高兴有选项和解释
    • 嗯,至少现在是这样。感谢您的启发。
    【解决方案3】:

    你可以这样做:

    [].slice.call(document.querySelectorAll(".test")).forEach(function(element) {
      element.addEventListener('click', function(event) {
        if (activeElement = document.querySelector(".test.active")) {
          activeElement.classList.remove("active");
        };
        event.target.classList.add('active');
      });
    });
    

    基本上,我们首先从活动元素中移除active 类,然后将其添加到目标中。

    JSBin

    【讨论】:

      【解决方案4】:

      另一种类似但更简单的方法:jsBin ;)

      var H4 = document.getElementsByClassName("test"), act;
      
      [].forEach.call(H4, function(el){
          el.addEventListener("click", function(){
             if(act) act.classList.remove("active");
             return (this.classList.toggle("active"), act=this);
          });
      });
      

      【讨论】:

      • 这些答案都很好,所以感谢@Josh 和其他人的回答。我唯一剩下的问题(因为我不是 JS 专家)使用此处提到的任何一种方法相对于另一种方法有哪些优点或缺点。尽可能简短,因为这是一个相当开放的问题,尤其是在不了解我的项目的情况下。
      • @Hambone Array.forEach.call 是在 ES5 (ECMAScript 5) 中引入的,因此它可能需要针对旧版浏览器的 polyfill。如果没有 polyfill,您应该使用标准 for(var i=0; i&lt;H4.length; i++){/* operate here over H4[i] */} 简单地循环所有元素。 classList 也是一个 ES5 特性。所以基本上我们都故意没有为老歌添加支持:) 这应该没问题,因为我们在 2015 年中期。否则使用更易读和更容易理解的代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 2012-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-04
      相关资源
      最近更新 更多