Evite los enlaces de eventos innecesarios.
Cuadro de comentarios con un botón de respuesta para cada comentario individual
const btns = document.getElementsByClassName('reply-btn'); for (let i = 0; i < btns.length; i++) { btns[i].addEventListener('click', showCommentContentAsPreview); } function showCommentContentAsPreview(e) { console.log('showCommentContentAsPreview()'); // CHECK IF THIS BUTTON ALREADY BINDED !!! const previewDiv = document.getElementById('preview'); const commentId = e.target.getAttribute('data-comment-id') const commentDiv = document.getElementById('comment-' + commentId); const commentText = commentDiv.querySelector('p').innerText const closeReplyBtn = previewDiv.querySelector('button'); const previewContent = previewDiv.querySelector('.preview-content'); // set to preview previewContent.innerText = commentText; // show reply close button closeReplyBtn.classList.remove('hidden'); // bind EventListener to "reply close button" closeReplyBtn.addEventListener('click', closeReply) function closeReply() { console.log('bind to btn'); previewContent.innerText = ''; this.removeEventListener('click', closeReply); closeReplyBtn.classList.add('hidden'); } } .hidden { display: none; } .comment { border-bottom: 1px solid #000; padding: 5px; } .preview { background-color: #ccc; padding: 20px; margin-top: 20px; } <div> <!-- comment list --> <div id="comment-1" class="comment"> <p>Comment Content 1</p> <button class="reply-btn" data-comment-id="1">reply</button> </div> <div id="comment-2" class="comment"> <p>Comment Content 2</p> <button class="reply-btn" data-comment-id="2">reply</button> </div> </div> <!-- output --> <div> <div id="preview" class="preview"> <div class="preview-content"></div> <button class="hidden">Close Preview</button> </div> </div>Cuando prueba el ejemplo, se producen los siguientes dos escenarios:
Haga clic en responder una vez y luego haga clic en "cerrar vista previa"
Haga clic en responder varias veces y luego en "cerrar vista previa".
¿Cómo puedo evitar múltiples enlaces al mismo botón? Ya estoy pensando en singleton.
En lugar de vincular un oyente a cada elemento de la serie, puede vincular un solo oyente una vez en un padre común de todos ellos y luego usar element.matches() para determinar si el destino del clic es el que desea antes de hacer más. trabajar. Vea el siguiente ejemplo:
function logTextContent (elm) { console.log(elm.textContent); } function handleClick (ev) { if (ev.target.matches('.item')) { logTextContent(ev.target); } } document.querySelector('ul.list').addEventListener('click', handleClick); <ul class="list"> <li class="item">Item 1</li> <li class="item">Item 2</li> <li class="item">Item 3</li> <li class="item">Item 4</li> <li class="item">Item 5</li> </ul>Con los útiles consejos de @Zephyr y @jsejcksn, he vuelto a escribir el código de la pregunta anterior. Por lo tanto, he logrado mi objetivo de evitar múltiples enlaces idénticos a un elemento.
const container = document.getElementById('comment-container'); const previewDiv = document.getElementById('preview'); const closeReplyBtn = previewDiv.querySelector('button'); const previewContent = previewDiv.querySelector('.preview-content'); container.addEventListener('click', handleClick); function handleClick(ev) { if (ev.target.matches('.reply-btn')) { if (ev.target.getAttribute('listener') !== 'true') { removeOtherListenerFlags(); ev.target.setAttribute('listener', 'true'); showCommentContentAsPreview(ev); } } if (ev.target.matches('#preview button')) { previewContent.innerText = ''; closeReplyBtn.classList.add('hidden'); removeOtherListenerFlags(); } } function showCommentContentAsPreview(e) { console.log('showCommentContentAsPreview()'); const commentId = e.target.getAttribute('data-comment-id') const commentDiv = document.getElementById('comment-' + commentId); const commentText = commentDiv.querySelector('p').innerText // set to preview previewContent.innerText = commentText; // show reply close button closeReplyBtn.classList.remove('hidden'); } function removeOtherListenerFlags() { const replyBtns = container.querySelectorAll('.reply-btn') Object.keys(replyBtns).forEach((el) => { replyBtns[el].removeAttribute('listener'); }) } .hidden { display: none; } .comment { border-bottom: 1px solid #000; padding: 5px; } .preview { background-color: #ccc; padding: 20px; margin-top: 20px; } <div id="comment-container"> <div id="comment-listing"> <!-- comment list --> <div id="comment-1" class="comment"> <p>Comment Content 1</p> <button class="reply-btn" data-comment-id="1">reply 1</button> </div> <div id="comment-2" class="comment"> <p>Comment Content 2</p> <button class="reply-btn" data-comment-id="2">reply 2</button> </div> </div> <!-- output --> <div> <div id="preview" class="preview"> <div class="preview-content"></div> <button class="hidden">Close Preview</button> </div> </div> </div>Genial y gracias!