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

时间:2018-03-11 19:03:15

标签: javascript html

我在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>

我想创建一个从特定div返回h2文本内容的onclick方法。我尝试使用以下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”)。

6 个答案:

答案 0 :(得分:2)

试试这个

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的值是它可以达到的最大值。因此,在像这样的函数中隔离相同的工作。该函数将iindex的值存储为您期望的原始值。

答案 1 :(得分:2)

替换

var i = 0

通过

let i = 0

你已经完成了。

详细解释为here

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

问题的原因:缺乏理解scope

选中此示例以了解问题:

var创建function scope

&#13;
&#13;
var funcs = []

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

funcs.forEach(function(func) {
  func()
})
&#13;
&#13;
&#13;

虽然您可能希望此forEach循环导致正在打印09,但您会获得10次10。造成这种情况的原因是使用i关键字声明变量var,这会创建function scope,导致function中的每个funcs持有引用相同的 i变量。在执行forEach循环时,先前的for - 循环已结束且i保持10(从上次迭代开始的9 ++)。

比较创建let而不是block scope的ES6&#39; function scope在这方面的行为:

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

&#13;
&#13;
var funcs = []

for (let i = 0; i < 10; i++) {
  funcs.push(function() {
    console.log(i)
  })
}

funcs.forEach(function(func) {
  func()
})
&#13;
&#13;
&#13;

由于let创建block scopefor循环的每次迭代都有其自己的&#34;变量i

使用IIFE包装器

的ES5解决方案

如果你需要一个ES5解决方案,一个IIFE( i 立即 i nvoked f unction e xpression)包装将是要走的路:

&#13;
&#13;
var funcs = []

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

funcs.forEach(function(func) {
  func()
})
&#13;
&#13;
&#13;

此处,i作为参数传递给存储其自己的副本value的每个函数。

for..in循环也是如此:

&#13;
&#13;
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()
})
&#13;
&#13;
&#13;

同样,funcs中的所有函数都将reference保持为相同的key,因为var key创建了一个位于for..in循环之外的函数作用域。同样,let会产生您可能更期待的结果:

&#13;
&#13;
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()
})
&#13;
&#13;
&#13;

还要比较优秀的(!)书

  

Nicholas C. Zakas: "Understanding ES6",没有淀粉压榨,p。 8-9。

从中获取了这些例子。

答案 2 :(得分:1)

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

将内容定义移到onclick函数中。

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

Working fiddle

答案 3 :(得分:0)

您可以尝试以下解决方案。

  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)
       }
     })

答案 4 :(得分:0)

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

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>

答案 5 :(得分:0)

假设您不想更改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);

EDIT 如果你想更具体,只从你的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);
}