繁体   English   中英

如何使 JavaScript 事件侦听器减少重复?

[英]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.

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