【问题标题】:Event Delegation, how to target a specific span inside a div事件委托,如何定位 div 内的特定跨度
【发布时间】:2017-01-04 18:29:30
【问题描述】:

给定一堆像这样的 div:

<div class="itemGrid">
    <div id="itemOne" class="fruit">
       <span> Banana </span>
          ????
        </div>

     <div id="itemTwo" class="fruit">
        <span> Apple </span>
          ????
      </div>
</div>

当我点击这些 div 时,我希望能够使用事件委托来获取跨度的值(所以只是文本)。

有了这个我得到了一切,文本和符号,但我似乎不能只得到范围内的文本:

const fruitButtons = document.querySelectorAll(".fruit span");
const grid = document.querySelector(".itemGrid");

grid.addEventListener("click", function(e) {
  if (e.target.nodeName == "DIV") {
    console.log(e.target.textContent)
  }
})

【问题讨论】:

    标签: javascript event-delegation


    【解决方案1】:

    您的代码不是正确的event delegation

    您应该检查您是否在div 内部单击了class=fruit。然后你可以从它的span后代中提取text

    grid.addEventListener("click", function(e) {
        let node = e.target;
        let div = null;
    
        // first let's check if we clicked inside div with class fruit by going up the DOM tree
        while(node !== this){
            if(node.hasClass("fruit")){
                div = node;
                break;
            }
    
            node = node.parentNode;
        }
    
        // if we clicked inside, log the value of span
        if(div !== null){
            console.log(div.querySelector("span").textContent);
        }
    });
    

    【讨论】:

    • 这是一个可靠的答案,但 hasClass 不是有效的 Javascript 函数。你应该改用node.classList.contains("fruit")
    【解决方案2】:

    使用getElementsByTagName() 查找目标下的span 元素。

    编辑:

    正如所指出的,人们可以解释 隐式 要求,即用户应该能够单击 span 元素并记录该元素的内容。通过添加 while 循环来搜索祖先链,添加了对此的支持:

    //search ancestors for div in case user clicks on span element
    while (target.nodeName !== "DIV" && e.target.parentNode !== null) {
        target = e.target.parentNode;
    }
    

    const fruitButtons = document.querySelectorAll(".fruit span");
    const grid = document.querySelector(".itemGrid");
    
    grid.addEventListener("click", function(e) {
      var target = e.target;
      //search ancestors for div in case user clicks on span element
      while (target.nodeName !== "DIV" && e.target.parentNode !== null) {
          target = e.target.parentNode;
      }
      if (target.nodeName == "DIV") {
        var spans = target.getElementsByTagName('span');
        if (spans.length) {
          console.log(spans[0].textContent);
        }
      }
    })
    <div class="itemGrid">
      <div id="itemOne" class="fruit">
        <span> Banana </span>
        ?
      </div>
    
      <div id="itemTwo" class="fruit">
        <span> Apple </span>
        ?
      </div>
    </div>

    【讨论】:

    • 这仅在您单击图像时有效。如果您单击&lt;div&gt;s,OP 希望能够获取文本。
    • 已更新示例以适应该要求。
    【解决方案3】:

    稍微修改一下场景:

    const fruitButtons = document.querySelectorAll(".fruit > span");
    const gridItems = document.querySelectorAll(".fruit");
    
    // Loop through the div.fruit elements:
    gridItems.forEach(function(div){
      
      // Wire each div.fruit to a click handler:
      div.addEventListener("click", function(e){
        // When clicked, look for the first span within the div and get its text
        console.log(div.querySelector("span").textContent);
      }); 
    });
    <div class="itemGrid">
        <div id="itemOne" class="fruit">
           <span> Banana </span>
              ?
         </div>
    
         <div id="itemTwo" class="fruit">
            <span> Apple </span>
              ?
          </div>
    </div>

    【讨论】:

    • 您的答案在我投反对票时不正确;现在也不是,因为如果我点击主要的div,它会失败,而不是class=fruit
    • 两者都按我的意愿工作,我不知道你为什么很难过:) 谢谢。
    • @bobjoe 你知道你可以删除自己的 cmets,对吧?
    • 这与事件委托无关
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-10
    • 1970-01-01
    • 2018-08-24
    相关资源
    最近更新 更多