我是 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";
我认为原因是当函数尝试附加监听器时,事件变量已经超出了范围。这正是我从研究中收集到的信息。总而言之,我很困惑,甚至不确定这是否是正确的方法。我想我有一些问题是:
- 为什么“event”在通过 onclick 属性传递时可以作为变量工作,但在作为参数传递给通过 for 循环调用的函数时却不能?我想我已经回答了这个问题,但也许更有知识的人可以提供更好的描述。
- 我的 for 循环似乎不必要地复杂。我在这里把事情复杂化了吗?我猜是"is"。
感谢任何帮助。
最佳答案
当您像这样声明事件处理程序时 - tab[i].addEventListener('click', tabbedWindows(event,c), false);
,您将调用 tabbedWindows
具有 未定义
值。由于 evt
是 未定义
,此语句 - evt.currentTarget
- 会引发错误。
您需要将第二个参数传递给事件处理程序,因为您需要从“data-target”选项卡获取的内容 ID。但是,该选项卡是事件的目标,单击它即可获取信息。我重构了代码,并删除了冗余内容。
const tabLinks = document.querySelectorAll(".tablinks");
const tabContents = document.querySelectorAll(".tabcontent");
const activateTab = target => {
const contentId = target.getAttribute('data-target');
// Get all elements with class="tabcontent" and hide them, and show the current tab
tabContents.forEach(tabContent => {
tabContent.style.display = tabContent.id === contentId ? 'block' : 'none';
});
// Get all elements with class="tablinks" and remove the class "active"
tabLinks.forEach(tablink => {
tablink.classList.remove('active');
});
// Add an "active" class to the button that opened the tab
target.classList.add('active');
};
const tabbedWindows = evt => {
const target = evt.currentTarget;
activateTab(target);
}
document.querySelectorAll(".tablinks").forEach(tab => {
tab.addEventListener('click', tabbedWindows, false);
});
activateTab(tabLinks[0]);
<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>
上一个答案:
您可以使用柯里化(Currying)来获取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>
关于javascript - 如何解决 addEventListener : Cannot read property 'currentTarget' of undefined 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58494061/