[英]How to make JavaScript Event Listeners less repetitive?
我在思考优化此代码块的新方法时遇到了一些麻烦。 现在它看起来过于重复和冗长。 我可以与 EventListener 分开编写函数,但它只会使代码行数更多并使其更长。
let modalIntro = document.getElementById('modal-intro');
let buttonIntro = document.getElementById('button-intro');
let close = document.getElementsByClassName('close')[0];
buttonIntro.addEventListener ('click', function(){
modalIntro.classList.remove("out");
modalIntro.classList.add("in");
});
close.addEventListener('click', function (){
modalIntro.classList.add("out");
});
let modalWork = document.getElementById('modal-work');
let buttonWork = document.getElementById('button-work');
let close1 = document.getElementsByClassName('close')[1];
buttonWork.addEventListener ('click', function(){
modalWork.classList.remove("out");
modalWork.classList.add("in");
});
close1.addEventListener('click', function (){
modalWork.classList.add("out");
});
let modalAbout = document.getElementById('modal-about');
let buttonAbout = document.getElementById('button-about');
let close2 = document.getElementsByClassName('close')[2];
buttonAbout.addEventListener ('click', function(){
modalAbout.classList.remove("out");
modalAbout.classList.add("in");
});
close2.addEventListener('click', function (){
modalAbout.classList.add("out");
});
let modalContact = document.getElementById('modal-contact');
let buttonContact = document.getElementById('button-contact');
let close3 = document.getElementsByClassName('close')[3];
buttonContact.addEventListener ('click', function(){
modalContact.classList.remove("out");
modalContact.classList.add("in");
});
close3.addEventListener('click', function (){
modalContact.classList.add("out");
});
任何帮助将非常感激。
看到您有一个通用的命名模式,并假设关闭按钮是每个模式的子项,您可以执行以下操作:
注意我添加了modal.classList.remove('in');
到关闭按钮
function bindModals(modals) { modals.forEach(name => { let modal = document.getElementById(`modal-${name}`) let button = document.getElementById(`button-${name}`) let close = modal.querySelector('.close'); button.addEventListener ('click', function(){ modal.classList.remove('out'); modal.classList.add('in'); }); close.addEventListener('click', function (){ modal.classList.remove('in'); modal.classList.add('out'); }); }); } bindModals(['intro', 'work', 'about', 'contact'])
.out { display: none; } .in { display: block; border: 1px solid red; height: 200px; width: 400px; }
<section> <button id="button-intro">Intro</button> <button id="button-work">Work</button> <button id="button-about">About</button> <button id="button-contact">Contact</button> </section> <section id="modal-intro" class="out"> <button class="close">Close</button> <p>Intro Modal</p> </section> <section id="modal-work" class="out"> <button class="close">Close</button> <p>Work Modal</p> </section> <section id="modal-about" class="out"> <button class="close">Close</button> <p>About Modal</p> </section> <section id="modal-contact" class="out"> <button class="close">Close</button> <p>Contact Modal</p> </section>
最简单的方法是简单地创建一个函数:
function MakeModal(modalId, buttonId, closeId)
let modal = document.getElementById(modalId);
let button = document.getElementById(buttonId);
let close = document.getElementsById(closeId);
button.addEventListener ('click', function(){
modal.classList.remove("out");
modal.classList.add("in");
});
close.addEventListener('click', function (){
modal.classList.add("out");
});
}
然后您可以调用它:
MakeModal('modal-intro', 'button-into', 'close-intro');
MakeModal('modal-about', 'button-about', 'close-about');
MakeModal('modal-contact', 'button-contact', 'close-contact');
这只是编程基础知识: DRY 。
请注意,您需要将 ID 添加到关闭按钮而不是类(或者您可以将其重写为let close = modal.find('.close');
或其他东西,在这种情况下,您可以摆脱第三个参数closeId
)。 如果您严格遵守此处使用的命名约定,您甚至可以简化多个MakeModal(...)
调用:
['intro', 'about', 'contact'].forEach(function(e) {
MakeModal('modal-' + e, 'button-' + e, 'close-' + e);
});
或者,如果您去掉第三个参数并使用.find(...)
建议:
['intro', 'about', 'contact'].forEach(function(e) {
MakeModal('modal-' + e, 'button-' + e);
});
我无论如何都不是 jQuery 专家,但如果我没记错的话
modal.classList.remove("out");
modal.classList.add("in");
可以写成:
modal.classList.switchClass("out", "in");
您可以使用函数来获取元素 Id 以使其更短:
function getElem(el) {
return document.getElementById(el);
}
现在删除所有以下代码:
let modalIntro = document.getElementById('modal-intro');
let buttonIntro = document.getElementById('button-intro');
let modalWork = document.getElementById('modal-work');
let buttonWork = document.getElementById('button-work');
let modalContact = document.getElementById('modal-contact');
let buttonContact = document.getElementById('button-contact');
– 并用getElem('elem-id')
替换变量,例如下面给出
getElem('modal-intro').classList.remove("out");
getElem('modal-intro').classList.add("in");
同样,您可以使用通用函数按类获取 Element 并添加事件侦听器。
在没有任何 HTML 的情况下,我不确定这是否完全准确,但我可以尝试一些东西。
我看到每个模态都以相同的方式运行......我会为每个按钮添加一个属性来标识它激活哪个模态,以及一个类,以便我们可以引用所有这些:
<input type="button" value="intro" class="modalButton" id="button-intro" data-activates="modal-intro">
<input type="button" value="work" class="modalButton" id="button-work" data-activates="modal-work">
<input type="button" value="about" class="modalButton" id="button-about" data-activates="modal-about">
<input type="button" value="contact" class="modalButton" id="button-contact" data-activates="modal-contact">
现在我们可以用这行代码来引用每个和动作:
document.getElementsByClassName("modalButton").forEach(function(btn) {
btn.addEventListener ('click', function() {
var modal = document.getElementById(btn.getAttribute("data-activates"));
modal.classList.remove("out");
modal.classList.add("in");
});
});
假设按钮在模态内是直接的,如下所示:
<!-- Example of a modal with a close button -->
<div id="modal-intro" class="modal out">
<input type="button" class="close" value="close">
<!-- content -->
</div>
我们可以通过在 DOM 树中向上移动来到达模态:
document.getElementsByClassName("close").forEach(function(closeBtn) {
closeBtn.addEventListener ('click', function(){
// In this case the modal is the button's parent
closeBtn.parentElement.classList().remove("in");
closeBtn.parentElement.classList().add("out");
// P.S I also suppose you want to remove the "in" class
});
});
Obiouvsly,如果按钮在模态内部更深,你只需要调用“parentElement”属性直到你到达它。
这是另一种方法,它利用了相同的结构乘以三这一事实。 如果我使用 jQuery,这会更短,但我保留了原版,因为您似乎没有使用它:
document.querySelectorAll("nav a").forEach(a => a.addEventListener("click", function(e) { e.preventDefault(); // don't navigate to href // hide all modals, ie remove the one potentially still open document.querySelectorAll("#modals > div").forEach(modal => modal.classList.remove("in")); // finally, show modal document.getElementById(this.dataset.modal).classList.add("in"); })); document.querySelectorAll("#modals > div").forEach(modal => // for each modal, grab its close button modal.querySelector(".close").addEventListener("click", function(e) { e.preventDefault(); // don't navigate to href modal.classList.remove("in"); // and hide the modal }) );
#modals>div { position: fixed; width: 50%; left: 25%; box-sizing: border-box; border: 1px solid black; padding: 0.5em; top: -300px; transition: .5s } #modals .close { float: right } .in { top: 50px !important; }
<nav> <a data-modal="intro" href="">Intro</a> <a data-modal="work" href="">Work</a> <a data-modal="about" href="">About</a> </nav> <div id="modals"> <div id="intro"><a href="" class="close">X</a> <p>Intro modal</p> </div> <div id="work"><a href="" class="close">X</a> <p>Work modal</p> </div> <div id="about"><a href="" class="close">X</a> <p>About modal</p> </div> </div>
通过菜单链接的data-modal
将代码指向模data-modal
,我不再需要使用任何特定于元素的代码,从而产生理想的可重用代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.