繁体   English   中英

Javascript。 Onclick总是返回相同的对象

[英]Javascript. Onclick returns always the same object

我以以下方式在html文档中获得了16个具有相同类名的div

    <div class="game-selection-tab">
      <h2>30m + 15s</h2>
    </div>
    <div class="game-selection-tab">
      <h2>60m + 0s</h2>
    </div>
    <div class="game-selection-tab">
      <h2>Custom</h2>
    </div>

我想创建onclick方法,该方法从特定的div返回h2文本内容。 我试图通过使用以下JavaScript代码来解决此问题。

var selectionTabs = document.getElementsByClassName("game-selection-tab");

for(var i = 0; i < selectionTabs.length; i++){

  var tab = selectionTabs[i];
  var content = tab.getElementsByTagName("h2");
  tab.onclick = function(){
   console.log(content[0].textContent);
  }
}

问题是:无论我单击哪个div,程序总是从最后一个div返回h2文本内容(在本示例中为“ custom”)。

尝试这个

var selectionTabs = document.getElementsByClassName("game-selection-tab");

for(var i = 0; i < selectionTabs.length; i++){
  (function (index) {
      var tab = selectionTabs[index];
      var content = tab.getElementsByTagName("h2");
      tab.onclick = function(){
       console.log(content[0].textContent);
      }
  })(i);
}

问题是当事件附加到实际的DOM元素时,for循环执行完成并且i的值是它可以达到的最大值。 因此,在类似的函数中将其隔离。 该函数将i的值或本例中的index为您期望的原始值。

更换

var i = 0

通过

let i = 0

到此为止。

详细说明在这里

我将在下面引用我的答案以供您理解。

问题原因:缺乏了解scope

检查此示例以了解问题:

var创建function scope

 var funcs = [] for (var i = 0; i < 10; i++) { funcs.push(function() { console.log(i) }) } funcs.forEach(function(func) { func() }) 

尽管您可能希望此forEach循环导致打印09 ,但您会得到10乘以10 原因是使用var关键字声明了变量i ,该变量创建了一个function scope ,该function scope导致funcs每个function持有对相同 i变量的引用 在执行forEach循环时,前一个for循环已结束,并且i持有10(最后一次迭代的9 ++)。

比较一下ES6的let ,它创建block scope而不是function scope在这方面的表现:

let (ES6或正式的ES2015 )创建block scope

 var funcs = [] for (let i = 0; i < 10; i++) { funcs.push(function() { console.log(i) }) } funcs.forEach(function(func) { func() }) 

因为let创建了block scope ,所以for循环的每个迭代都有其“自己的”变量i

使用IIFE包装器的ES5解决方案

如果你需要一个ES5液,IIFE( mmediately nvoked˚FË上的表达)的包装将是要走的路:

 var funcs = [] for (var i = 0; i < 10; i++) { funcs.push((function(value) { return function() { console.log(value) } }(i))) } funcs.forEach(function(func) { func() }) 

在这里, i作为参数传递给每个存储自己的副本value

for..in循环也是如此:

 var funcs = [], obj = { first: "first", last: "last", always: "always" } for (var key in obj) { funcs.push(function() { console.log(key) }) } funcs.forEach(function(func) { // outputs: "always", "always", "always" func() }) 

同样,在所有功能funcs保持reference相同的key ,因为var key创建功能范围是生活在外面for..in循环。 再一次, let产生您可能希望得到的结果:

 var funcs = [], obj = { first: "first", last: "last", always: "always" } for (let key in obj) { funcs.push(function() { console.log(key) }) } funcs.forEach(function(func) { func() }) 

同时比较优秀的(!)书

尼古拉斯·扎卡斯(Nicholas C. Zakas):“ Understanding ES6” (不理解ES6) ,第8页。 8-9。

以此为例。

它始终显示相同的值,因为您是在onclick函数之外设置内容的。 在for循环之后, content指向最后一个h2。

将内容定义onclick函数中。

  tab.onclick = function(){
    var content = this.getElementsByTagName("h2");
    console.log(content[0].textContent);
  }

工作提琴

您可以尝试以下解决方案吗?

  var selectionTabs = document.getElementsByClassName("game-selection-tab");

     Object.keys(selectionTabs).forEach((data, index) => {
       var context = selectionTabs[data].getElementsByTagName("h2")[0].textContent;
       selectionTabs[data].onclick = function () {
         console.log(context)
       }
     })

试试这个简单的解决方案:

 var els = document.getElementsByClassName('game-selection-tab'); var index = 0; function getText() { alert(this.innerText || this.textContent); } for (; index < els.length; index++) { els[index].onclick = getText; } 
 <div class="game-selection-tab"> <h2>30m + 15s</h2> </div> <div class="game-selection-tab"> <h2>60m + 0s</h2> </div> <div class="game-selection-tab"> <h2>Custom</h2> </div> 

假设您不想更改HTML以在每个h2上都包含“ onclick”事件,那么此代码可能会帮助您:

document.addEventListener('click', function(e) {
  e = e || window.event;
  var target = e.target || e.srcElement,
    text = target.textContent || text.innerText;
        console.log(text);
}, false);

编辑如果您想更具体一些,并且仅从h2中获取内容,则可以使用以下方法:

h2s = document.getElementsByTagName('h2');
for (var i = 0; i < h2s.length; i++) {
  h2s[i].addEventListener('click', redirect, false);
}

function redirect(e) {
  var target = e.target || e.srcElement;
  var text = target.textContent || text.innerText;
  console.log(text);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM