【问题标题】:Parsing HTML5 data-attribute to document.querySelector将 HTML5 数据属性解析为 document.querySelector
【发布时间】:2020-09-13 05:41:38
【问题描述】:

我有三个带有 ID 和类的 HTML 按钮。其中两个还持有数据属性。

数据属性适用于它们应该更改其样式显示属性的元素。

基本思想是显示或隐藏段落元素。 我试图通过使用 querySelectors 和 for 循环而不是拥有多个事件侦听器来减少重复代码。 我一直在编写从 codepen 第 31 行开始的函数。我试过: document.querySelector(classbtns[i].getAttribute('data-value')).style.display = "inline"; 我得到: TypeError: document.querySelector(...) is null

我保留并注释掉了早期的代码块,以帮助您了解我正在尝试做什么。

请查看我的代码并链接到下面的代码笔:

html:

 <p id="toy-pictures-latest" class="panel">Latest Toy Pictures</p><br>
         <p id="toy-pictures-greatest" class="panel">Greatest Toy Pictures</p>

Toy Pictures
<button type="button" id="btnlatest" data-value="toy-pictures-latest" class="buttons">Latest</button>
<button type="button" id="btngreatest" data-value="toy-pictures-greatest class="buttons">Greatest</button></details></li>
<button type="button" id="clear-btn">Clear</button>

css:

 #toy-pictures-latest.panel{
    display: inline;
}

#toy-pictures-greatest.panel{
        display: inline;
}

js:

/*function fgreatest() {
   document.getElementById('toy-pictures-greatest').style.display = "inline";
   }*/

//The following function clears the p elements in class "panel" by changing the display value in css

function clearall()
{
var panels = document.querySelectorAll('.panel'), i;  
console.log("exe");  
for (i = 0; i < panels.length; ++i) {
  panels[i].style.display = "none";
}

}  

//This is the previous version of the querySelector.
//It required a new function for each <p> element id 

/*const classbtns = document.querySelectorAll(".buttons");

 for (let i = 0; i < classbtns.length; i++) {
     classbtns[i].addEventListener("click", fgreatest);
 }*/

//This is the attempt to grab the name of the element
//from the html data value property and change the css //style display to inline

 const classbtns = document.querySelectorAll(".buttons");
 
  for (let i = 0; i < classbtns.length; i++) {
     classbtns[i].addEventListener("click", function() {
     
     document.querySelector(classbtns[i].getAttribute('data-value')).style.display = "inline";
      });
  }

document.getElementById('clear-btn').addEventListener("click", clearall);

codepen

【问题讨论】:

    标签: javascript html dom queryselector


    【解决方案1】:

    我发现了两个问题:

    1. 在 HTML 中,按钮“btngretest”的数据值标记缺少结束引号。

    2. 由于您要按 ID 选择面板,因此您应该使用 '#' 作为前缀

      document.querySelector('#'+ classbtns[i].getAttribute('data-value')).style.display = "inline";

    【讨论】:

    • 没问题。同样正如@nzn 在另一个答案中所说,对于您的情况,最好使用“document.getElementById”
    • 当然,但是我不会了解 querySelector。
    【解决方案2】:

    当使用 document.querySelector 按 ID 选择元素时,您需要以“#”开头,这样可以:

    document.querySelector('#' + classbtns[i].getAttribute('data-value')).style.display = "inline";
          });
    

    但是你也可以使用

    document.getElementById(classbtns[i].getAttribute('data-value')).style.display = "inline";
    

    【讨论】:

      【解决方案3】:

      作为解决方案的补充,在获取数据属性时可能值得考虑旧的 MDN:

      [...],但标准定义了一种更简单的方法:可以通过数据集属性读取的 DOMStringmap。 https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes

      我个人也会选择活动的目标。比如:

      const attachListener = btn => btn.addEventListener('click', (e) => document.getElementById(e.target.dataset.value).style.display = 'inline';
      
      clsBtns.forEach(attachListener);
      

      【讨论】:

        【解决方案4】:

        这是一个更当前和简化的清洁方法,使用forEach 方法并使用event.target 方法定位我们点击的实际元素

        Event.target 将确保您定位正确的元素以获取其data-value - 如果您有很多按钮并相互嵌套,则此方法更好。

        您也可以使用新的dataset 方法代替使用getAtribute 方法

        使用data.set

         document.querySelector("#" + e.target.dataset.value).style.display = "inline";
        

        现场演示:

        function clearall() {
          var panels = document.querySelectorAll('.panel')
          panels.forEach(function(el) {
            el.style.display = "none";
          });
        }
        
        const classbtns = document.querySelectorAll(".buttons");
        classbtns.forEach(function(btn) {
          btn.addEventListener("click", function(e) {
            document.querySelector("#" + e.target.getAttribute('data-value')).style.display = "inline";
          })
        })
        
        //clear al;
        document.getElementById('clear-btn').addEventListener("click", clearall);
        #toy-pictures-latest.panel {
          display: none;
        }
        
        #toy-pictures-greatest.panel {
          display: none;
        }
        <p id="toy-pictures-latest" class="panel">Latest Toy Pictures</p><br>
        <p id="toy-pictures-greatest" class="panel">Greatest Toy Pictures</p>
        
        <br>
        Toy Pictures
        <button type="button" id="btnlatest" data-value="toy-pictures-latest" class="buttons">Latest</button>
        
        <button type="button" id="btngreatest" data-value="toy-pictures-greatest" class="buttons">Greatest</button>
        
        <button type="button" id="clear-btn">Clear</button>

        【讨论】:

        • 感谢您的帮助。我之前尝试了一些使用“forEach”的例子,但我没有让它们工作。我已将您的代码放在codepen 中进行测试。两种方法都很好,所以我可以在不同的浏览器上进行测试。谢谢。
        • @caston 很高兴为您提供帮助 :) ForEach 现在可以在所有浏览器上运行,如 MDN 中所述。我猜你的方法在使用它时可能是正确的。让我知道我是否可以帮助任何未来的伙伴。如果您遇到困难,请给我留言:)
        • 这是我在课程中需要做的浮动线框工作的一个很好的小分心,但现在我必须回到他们身上。
        • 我现在正在尝试添加“-footer”,但不确定确切的语法。我试过document.querySelector('#' + classbtns[i].getAttribute('data-value') + '-footer').style.display = "inline"; }); codepen
        • @caston 抱歉,我不确定你在说什么?您能否详细说明一下,如果问题不同,您可以添加另一个问题吗?
        猜你喜欢
        • 2013-05-17
        • 1970-01-01
        • 2020-08-05
        • 2012-07-18
        • 1970-01-01
        • 1970-01-01
        • 2015-10-07
        • 2019-01-11
        • 1970-01-01
        相关资源
        最近更新 更多