【问题标题】:Javascript in need of simplification - collapsible tabs需要简化的 Javascript - 可折叠标签
【发布时间】:2019-08-28 09:20:40
【问题描述】:

我已经编写了一些标签,它似乎运行良好,尽管我确信我可以使用更简洁的代码来实现这一点!我只是不确定现在该怎么做。我真的很感谢您对此提供一些帮助。

我不确定我想使用它的循环还是完全不同的东西?

我所做的方式显然有效,但它似乎没有必要且混乱,在此之后下一步是在选项卡下降时添加过渡效果。我不确定这是否允许我这样做。

function myFunction() {
  var a = document.getElementById("results1");
  var b = document.getElementById("results2");
  var c = document.getElementById("results3");
  var d = document.getElementById("title1"); 
  var e = document.getElementById("title2"); 
  var f = document.getElementById("title3"); 
  if (a.style.display === "none") {
    a.style.display = "block";
    b.style.display = "none";
    c.style.display = "none";
    d.style.backgroundColor = "#005FAA";
    e.style.backgroundColor = "lightgrey";
    f.style.backgroundColor = "lightgrey";
  } 
  else {
    a.style.display = "none";
    d.style.backgroundColor = "lightgrey";
  }
}

function myFunction1() {
  var a = document.getElementById("results1");
  var b = document.getElementById("results2");
  var c = document.getElementById("results3");
  var d = document.getElementById("title1"); 
  var e = document.getElementById("title2"); 
  var f = document.getElementById("title3"); 
  if (b.style.display === "none") {
    a.style.display = "none";
    b.style.display = "block";
    c.style.display = "none";
    d.style.backgroundColor = "lightgrey";
    e.style.backgroundColor = "#005FAA";
    f.style.backgroundColor = "lightgrey";
  } 
  else {
    b.style.display = "none";
    e.style.backgroundColor = "lightgrey";
  }
}

function myFunction2() {
  var a = document.getElementById("results1");
  var b = document.getElementById("results2");
  var c = document.getElementById("results3");
  var d = document.getElementById("title1"); 
  var e = document.getElementById("title2"); 
  var f = document.getElementById("title3"); 
  if (c.style.display === "none") {
    a.style.display = "none";
    b.style.display = "none";
    c.style.display = "block";
    d.style.backgroundColor = "lightgrey";
    e.style.backgroundColor = "lightgrey";
    f.style.backgroundColor = "#005FAA";
  } 
  else {
    c.style.display = "none";
    f.style.backgroundColor = "lightgrey";
  }
}
body{
margin: 10px;}

.title{
background-color:lightgrey;
width: 32%;
float: left;
text-align: center;
text-decoration:none;
color:white;
margin-right: 2%;
padding: 30px;
box-sizing: border-box;
}


.title:last-child{
margin-right:0px;
width:32%;}

.results{
background-color:#005FAA;
float:left;
width: 100%;
color: white;
padding: 30px;
box-sizing: border-box;
}
<div class="container">
    <div id="title1" class="title" onclick="myFunction()">
        <h4>Item 1</h4>
    </div> 
    <div id="title2" class="title" onclick="myFunction1()">
        <h4>Item 2</h4>
    </div> 
    <div id="title3" class="title" onclick="myFunction2()">
        <h4>Item 3</h4>
    </div> 
</div>


<div class="results" id="results1" style="display:none;">Item 1</div>
<div class="results" id="results2" style="display:none">Item 2</div>
<div class="results" id="results3" style="display:none">Item 3</div>

【问题讨论】:

    标签: javascript html css collapse


    【解决方案1】:

    也许是这样的?您已经在使用 JQuery,因此可以将其模块化并使用它来帮助您实现向下转换效果(如果您愿意,您也可以向上转换它们)。

    const tabs = {
      animating: false,
      toggleResults: function(thatTab) {
        const thatResult = $(`[data-title="${thatTab.attr('id')}"]`);
        thatTab.toggleClass('activeTab');
        thatResult.toggleClass("openedResult");
        tabs.animating = true;
        thatResult.slideToggle("fast", function() {
          tabs.animating = false;
        });
      },
      init: function() {
        $(".title").click(function() {
          const thatTab = $(this);
          const openedResult = $('.openedResult');
          const thatTabId = thatTab.attr("id");
          const openedResultTitle = openedResult.data('title');
    
          if (!tabs.animating) {
            $('.activeTab').removeClass('activeTab');
            openedResult.removeClass('openedResult').hide();
            if (thatTabId !== openedResultTitle) {
              tabs.toggleResults(thatTab);
            }
          }
        });
      }
    };
    
    $(function() {
      tabs.init();
    });
    body {
      margin: 0;
    }
    
    .container {
      display: flex;
      justify-content: space-between;
      width: 100%;
    }
    
    .title {
      background-color: lightgrey;
      flex-basis: 32%;
      transition: background-color 0ms;
      text-align: center;
      color: white;
      padding: 30px;
      box-sizing: border-box;
    }
    
    .activeTab {
      background-color: #005faa;
      transition: background-color 100ms;
    }
    
    .results {
      background-color: #005faa;
      display: none;
      width: 100%;
      color: white;
      padding: 30px;
      box-sizing: border-box;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="container">
      <div id="title1" class="title">
        <h4>Item 1</h4>
      </div>
      <div id="title2" class="title">
        <h4>Item 2</h4>
      </div>
      <div id="title3" class="title">
        <h4>Item 3</h4>
      </div>
    </div>
    
    
    <div class="results" data-title="title1">Item 1</div>
    <div class="results" data-title="title2">Item 2</div>
    <div class="results" data-title="title3">Item 3</div>

    【讨论】:

    • 是什么让你认为 OP 已经在使用 jQuery?我没有看到任何迹象。
    • 在这个问题的第一个版本中,我以为我在脚本标签中看到了一个 JQuery CDN,但它已经不存在了。我可以用 Vanilla JS 重写这个建议。
    • 这是有道理的。我认为它实际上并不存在。我相信我将代码移动到 sn-p 是唯一的编辑。但如果你是这么想的,那现在就更有意义了。
    【解决方案2】:

    试试这个,你可以在所有三个 div 上调用相同的函数并传递它们的 id 来查找当前 id。

    <!DOCTYPE html>
    <style type="text/css">
    
    body{
    margin: 10px;}
    
    .title{
    background-color:lightgrey;
    width: 32%;
    float: left;
    text-align: center;
    text-decoration:none;
    color:white;
    margin-right: 2%;
    padding: 30px;
    box-sizing: border-box;
    }
    
    
    .title:last-child{
    margin-right:0px;
    width:32%;}
    
    .results{
    background-color:#005FAA;
    float:left;
    width: 100%;
    color: white;
    padding: 30px;
    box-sizing: border-box;
    }
    
    .active{
      display = "block"
    }
    .inactive{
      display : "none"
      backgroundColor:"#005FAA"
    }
    
    </style>
    
    <div class="container">
        <div id="title1" class="title" onclick="ActivateTab(1)">
            <h4>Item 1</h4>
        </div> 
        <div id="title2" class="title" onclick="ActivateTab(2)">
            <h4>Item 2</h4>
        </div> 
        <div id="title3" class="title" onclick="ActivateTab(3)">
            <h4>Item 3</h4>
        </div> 
        <button onclick="ActivateTab(2)">Test</button>
    </div>
    
    
    <div class="results" id="results1" style="display:none;">Item 1</div>
    <div class="results" id="results2" style="display:none">Item 2</div>
    <div class="results" id="results3" style="display:none">Item 3</div>
    
    <script> 
    
    function ActivateTab(id){
      let results = document.querySelectorAll(".results")
      let titles = document.querySelectorAll(".title")
    
      results.forEach((elementResut,index) =>{
        let elementTitle = titles[index];
          if(elementResut.id === "results"+id 
          && elementResut.style.display === "none")
          {
                elementResut.style.display = "block";
                elementTitle.style.backgroundColor = "#005FAA";
          }
          else{
            elementResut.style.display = "none";    
            elementTitle.style.backgroundColor = "lightgrey";
          }
      }); 
    }
    
    </script>
    

    【讨论】:

    • 这在 IE 中不起作用。未定义的变量,我不知道为什么会这样?
    • 我现在已经解决了 - 你不能在 IE 中使用箭头函数,并且 forEach 也需要更改
    【解决方案3】:

    这是一种可能的清理方法:

    function myFunction(title) {
      var results = [...document.getElementsByClassName("results")]
      results.forEach(function(r) {
        if (title.dataset.for == r.id) {
          r.style.display = "block";
        } else {
          r.style.display = "none";
        }    
      });
    
      var titles = [...document.getElementsByClassName("title")]
      titles.forEach(function(t) {
        if (t == title) {
          t.style.backgroundColor = "#005FAA"
        } else { 
          t.style.backgroundColor = "lightgrey"
        }
      });
    }
    body{
    margin: 10px;}
    
    .title{
    background-color:lightgrey;
    width: 32%;
    float: left;
    text-align: center;
    text-decoration:none;
    color:white;
    margin-right: 2%;
    padding: 30px;
    box-sizing: border-box;
    }
    
    
    .title:last-child{
    margin-right:0px;
    width:32%;}
    
    .results{
    background-color:#005FAA;
    float:left;
    width: 100%;
    color: white;
    padding: 30px;
    box-sizing: border-box;
    }
    <div class="container">
        <div id="title1" data-for="results1" class="title" onclick="myFunction(this)">
            <h4>Item 1</h4>
        </div> 
        <div id="title2" data-for="results2" class="title" onclick="myFunction(this)">
            <h4>Item 2</h4>
        </div> 
        <div id="title3" data-for="results3" class="title" onclick="myFunction(this)">
            <h4>Item 3</h4>
        </div> 
    </div>
    
    
    <div class="results" id="results1" style="display:none;">Item 1</div>
    <div class="results" id="results2" style="display:none">Item 2</div>
    <div class="results" id="results3" style="display:none">Item 3</div>

    我用一个接受代表标题元素的参数的函数替换了您的三个函数。在事件处理程序中,我们只需将this 传递给该函数。然后在函数中,我们循环遍历可能需要更改的内容(titleresults 节点)测试我们是否正在使用匹配元素或不同元素并基于此选择行为。

    为了将title 元素与results 链接起来,我为其添加了data-for 属性。还有很多其他方法可以做到这一点,包括使用正则表达式来查找基本 id(例如title2 ~&gt; 2results2 ~&gt; 2)并匹配这些。但这应该能让你继续前进。

    我可能会对此进行更多清理,但这应该会大大简化。

    更新

    评论指出,上述内容不允许完全取消选项卡。鉴于此,重构更多并使用共享基 id 方法似乎更好。这是用这种方式编写的另一个版本:

    function myFunction(title) {
      var id = title.id.match(/^\D*(\d+)$/)[1]
      var hidden = document.getElementById(`results${id}`).style.display !== 'block';
    
      [...document.getElementsByClassName("results")].forEach(function(r) {
        r.style.display = "none";    
      });
      [...document.getElementsByClassName("title")].forEach(function(t) {
        t.style.backgroundColor = "lightgrey";
      });
    
      if (hidden) {
        document.getElementById(`results${id}`).style.display = 'block';
        document.getElementById(`title${id}`).style.backgroundColor = '#005FAA';
      }
    }
    body{
    margin: 10px;}
    
    .title{
    background-color:lightgrey;
    width: 32%;
    float: left;
    text-align: center;
    text-decoration:none;
    color:white;
    margin-right: 2%;
    padding: 30px;
    box-sizing: border-box;
    }
    
    
    .title:last-child{
    margin-right:0px;
    width:32%;}
    
    .results{
    background-color:#005FAA;
    float:left;
    width: 100%;
    color: white;
    padding: 30px;
    box-sizing: border-box;
    }
    <div class="container">
        <div id="title1" class="title" onclick="myFunction(this)">
            <h4>Item 1</h4>
        </div> 
        <div id="title2" class="title" onclick="myFunction(this)">
            <h4>Item 2</h4>
        </div> 
        <div id="title3" class="title" onclick="myFunction(this)">
            <h4>Item 3</h4>
        </div> 
    </div>
    
    
    <div class="results" id="results1" style="display:none;">Item 1</div>
    <div class="results" id="results2" style="display:none">Item 2</div>
    <div class="results" id="results3" style="display:none">Item 3</div>

    【讨论】:

    • 谢谢你 - 虽然这不允许取消选择标签,这对于我需要它的关键
    • @JamieRicketts:添加了一个允许完全取消选择的更新版本。它可能仍然是更简洁的代码。
    猜你喜欢
    • 2016-08-31
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 1970-01-01
    • 2012-12-30
    • 1970-01-01
    • 2011-04-19
    相关资源
    最近更新 更多