如何解决addEventListener的问题:无法读取未定义的属性'currentTarget'

问题描述 投票:0回答:2

我是JavaScript的新手,请多多包涵。

我正在尝试使用JavaScript为特定内容的内容生成选项卡式窗口。 HTML看起来像这样:

<div class="tab-win" id="tablinks-d38e44">
   <button class="tablinks" data-target="tab-bash-d38e44">bash</button>
   <button class="tablinks" data-target="tab-gui-d38e44">gui</button>
</div>

<div class="tabcontents" id="tabcontents-d38e44">
   <div class="tabcontent" id="tab-bash-d38e44">This is bash.</div>
   <div class="tabcontent" id="tab-gui-d38e44">This is plain old GUI...</div>
</div>

<p class="p">Here is another one.</p>

<div class="tab-win" id="tablinks-d38e56">
   <button class="tablinks" data-target="tab-bash-d38e56">bash</button>
   <button class="tablinks" data-target="tab-gui-d38e56">gui</button>
</div>

<div class="tabcontents" id="tabcontents-d38e56">
   <div class="tabcontent" id="tab-bash-d38e56">This is bash #2.</div>
   <div class="tabcontent" id="tab-gui-d38e56">This is plain old GUI..#2.</div>
</div>

</div>

我已经把这个功能拼凑在一起了。

function tabbedWindows(evt, env) {
  // Declare all variables
  var i, tabcontent, tablinks;

  // Get all elements with class="tabcontent" and hide them
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }

  // Get all elements with class="tablinks" and remove the class "active"
  tablinks = document.getElementsByClassName("tablinks");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }

  // Show the current tab, and add an "active" class to the button that opened the tab
  document.getElementById(env).style.display = "block";
  evt.currentTarget.className += " active";
}

如果我直接向按钮元素添加onclick属性,如下所示:

onclick="tabbedWindows(event,'content-id')"

效果很好。但是,我试图将关注点分离,并希望动态添加事件。我正在尝试以下操作:

const tab = document.querySelectorAll(".tablinks");
const content = document.querySelectorAll(".tabcontent");

for (let i = 0; i < tab.length; i++) {
    let conId = tab[i].getAttribute('data-target');
    let conArray = Array.from(content);
    let con = conArray.find((c) => c.getAttribute('id') === conId);
    let c = con.getAttribute('id');
    tab[i].addEventListener('click', tabbedWindows(event,c), false);
}

由于以下错误而无法使用:main.js:23 Uncaught TypeError:无法读取未定义的属性'currentTarget'。它失败的行是:

evt.currentTarget.className += " active";

我认为原因是当函数尝试附加侦听器时,事件变量已经超出范围。这正是我从研究中得到的东西。我对它的长或短感到困惑,甚至不确定这是否是正确的方法。我想我有一些问题:

  1. 为什么'event'在通过onclick属性传递时充当变量,而在作为参数传递给通过for循环调用的函数时却不起作用?我想我已经回答了这个问题,但也许更有知识的人可以提供更好的描述。
  2. 我的for循环似乎不必要地令人费解。我在这里把事情复杂化了吗?我猜是的。

感谢您的任何帮助。

javascript dom
2个回答
0
投票

[这样声明事件处理程序-tab[i].addEventListener('click', tabbedWindows(event,c), false);时,将使用tabbedWindows值调用undefined。由于evtundefined,因此此语句-evt.currentTarget-引发错误。

您可以使用部分应用程序获取env,并返回一个等待事件对象的新函数:

/** get env and return a new function that will be called with the event object **/
const tabbedWindows = env => evt => {
  // Declare all variables
  var i, tabcontent, tablinks;

  // Get all elements with class="tabcontent" and hide them
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }

  // Get all elements with class="tablinks" and remove the class "active"
  tablinks = document.getElementsByClassName("tablinks");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }

  // Show the current tab, and add an "active" class to the button that opened the tab
  document.getElementById(env).style.display = "block";
  evt.currentTarget.className += " active";
}

const tab = document.querySelectorAll(".tablinks");
const content = document.querySelectorAll(".tabcontent");

for (let i = 0; i < tab.length; i++) {
  let conId = tab[i].getAttribute('data-target');
  let conArray = Array.from(content);
  let con = conArray.find((c) => c.getAttribute('id') === conId);
  let c = con.getAttribute('id');
  tab[i].addEventListener('click', tabbedWindows(c), false); // call tabbedWindows with c
}
<div class="tab-win" id="tablinks-d38e44">
  <button class="tablinks" data-target="tab-bash-d38e44">bash</button>
  <button class="tablinks" data-target="tab-gui-d38e44">gui</button>
</div>

<div class="tabcontents" id="tabcontents-d38e44">
  <div class="tabcontent" id="tab-bash-d38e44">This is bash.</div>
  <div class="tabcontent" id="tab-gui-d38e44">This is plain old GUI...</div>
</div>

<p class="p">Here is another one.</p>

<div class="tab-win" id="tablinks-d38e56">
  <button class="tablinks" data-target="tab-bash-d38e56">bash</button>
  <button class="tablinks" data-target="tab-gui-d38e56">gui</button>
</div>

<div class="tabcontents" id="tabcontents-d38e56">
  <div class="tabcontent" id="tab-bash-d38e56">This is bash #2.</div>
  <div class="tabcontent" id="tab-gui-d38e56">This is plain old GUI..#2.</div>
</div>

</div>

0
投票
Hi Jason,

  May be you should just try doing this first

*for (let i = 0; i < tab.length; i++) {
    tab[i].addEventListener('click', tabbedWindows, false);
}*

and in your tabbedWindows function you can add these lines

function tabbedWindows(event) { 

     let conId = event.currentTarget.getAttribute('data-target');
     let conArray = Array.from(content);
     let con = conArray.find((c) => c.getAttribute('id') === conId);
     let c = con.getAttribute('id');

     // and then rest of your code goes here

}
© www.soinside.com 2019 - 2024. All rights reserved.