如何用原生JS优化商品模态框代码?面向新手简化实现
商品模态框代码优化方案
我正在帮朋友开发一个西班牙语网站,需求是通过弹窗(模态框)向用户展示特定商品的详细信息。功能已实现,但代码冗余度高,希望了解优化方法。以下是原始的HTML和JS代码,以及对应的优化方案:
原始HTML代码
<div class="overlay hidden"></div> <!-- 商品卡片按钮 --> <button type="button" class="products__cards__card" id="pa-card"> <img src="assets/img/cards/piña.png" alt="pina-deshidratada"> <div class="product-info"> <h3>Piña Golden</h3> <p>Dulce y deliciosa</p> </div> </button> <button type="button" class="products__cards__card" id="arandano-card"> <img class="os-img" src="assets/img/cards/arandano.png" alt="arandano-deshidratado"> <div class="product-info"> <h3>Arándano</h3> <p>El punto perfecto entre dulce y ácido</p> </div> </button> <!-- 商品模态框 --> <div class="modal hidden" id="pa-modal"> <h3>Piña Golden</h3> <p></p> <div class="modal__info"> <span>100 gr.</span><span class="modal__info__price">S/16.00</span> </div> <button type="button" class="modal-button button">Regresar</button> </div> <div class="modal hidden" id="arandano-modal"> <h3>Arándano</h3> <p></p> <div class="modal__info"> <span>100 gr.</span><span class="modal__info__price">S/18.00</span> </div> <button type="button" class="modal-button button">Regresar</button> </div>
原始JS代码
// 卡片变量 const paButtonCard = document.querySelector("#pa-card"); const arandanoButtonCard = document.querySelector("#arandano-card"); // 模态框变量 const paModal = document.querySelector("#pa-modal"); const arandanoModal = document.querySelector("#arandano-modal"); const aguaymantoModal = document.querySelector("#aguaymanto-modal"); // 关闭按钮组 const closeModalButton = document.querySelectorAll(".modal-button"); // 遮罩层 const overlay = document.querySelector(".overlay"); // 隐藏模态框和遮罩层的函数 const closeModal = function () { overlay.classList.add("hidden"); paModal.classList.add("hidden"); arandanoModal.classList.add("hidden"); }; // 绑定关闭按钮事件 for (let i = 0; i < closeModalButton.length; i++) { closeModalButton[i].addEventListener("click", closeModal); } // 点击遮罩层关闭 overlay.addEventListener("click", closeModal); // 打开菠萝模态框 paButtonCard.addEventListener("click", function () { paModal.classList.remove("hidden"); overlay.classList.remove("hidden"); }); // 打开蓝莓模态框 arandanoButtonCard.addEventListener("click", function () { arandanoModal.classList.remove("hidden"); overlay.classList.remove("hidden"); });
优化方案
1. HTML结构优化:用数据属性关联按钮与模态框
给每个商品按钮添加data-modal-target属性,直接指定对应的模态框ID,避免硬编码关联逻辑:
<button type="button" class="products__cards__card" id="pa-card" data-modal-target="#pa-modal"> <!-- 内容不变 --> </button> <button type="button" class="products__cards__card" id="arandano-card" data-modal-target="#arandano-modal"> <!-- 内容不变 --> </button>
2. JS逻辑优化:消除冗余,统一处理
不需要单独定义每个按钮和模态框的变量,通过批量选择器和循环实现通用逻辑:
// 批量获取元素 const productCards = document.querySelectorAll(".products__cards__card"); const modals = document.querySelectorAll(".modal"); const closeModalButtons = document.querySelectorAll(".modal-button"); const overlay = document.querySelector(".overlay"); // 打开指定模态框 function openModal(targetSelector) { const targetModal = document.querySelector(targetSelector); targetModal.classList.remove("hidden"); overlay.classList.remove("hidden"); } // 关闭所有模态框和遮罩层 function closeAllModals() { overlay.classList.add("hidden"); modals.forEach(modal => modal.classList.add("hidden")); } // 绑定所有商品卡片的点击事件 productCards.forEach(card => { card.addEventListener("click", () => { openModal(card.dataset.modalTarget); }); }); // 绑定所有关闭按钮事件 closeModalButtons.forEach(button => { button.addEventListener("click", closeAllModals); }); // 点击遮罩层关闭 overlay.addEventListener("click", closeAllModals); // 可选:按ESC键关闭模态框 document.addEventListener("keydown", (e) => { if (e.key === "Escape") closeAllModals(); });
3. 进阶优化:动态填充模态框内容(可选)
如果商品数量较多,可以把商品信息存在按钮的data-*属性中,动态填充到模态框,甚至只保留一个模态框模板,完全消除重复HTML:
修改后的按钮
<button type="button" class="products__cards__card" data-modal-target="#product-modal" data-name="Piña Golden" data-weight="100 gr." data-price="S/16.00"> <!-- 内容不变 --> </button> <button type="button" class="products__cards__card" data-modal-target="#product-modal" data-name="Arándano" data-weight="100 gr." data-price="S/18.00"> <!-- 内容不变 --> </button>
单个模态框模板
<div class="modal hidden" id="product-modal"> <h3></h3> <p></p> <div class="modal__info"> <span></span><span class="modal__info__price"></span> </div> <button type="button" class="modal-button button">Regresar</button> </div>
对应的JS逻辑
// 打开模态框并填充内容 function openModal(targetSelector, productData) { const targetModal = document.querySelector(targetSelector); targetModal.querySelector("h3").textContent = productData.name; targetModal.querySelector(".modal__info span:first-child").textContent = productData.weight; targetModal.querySelector(".modal__info__price").textContent = productData.price; targetModal.classList.remove("hidden"); overlay.classList.remove("hidden"); } // 绑定卡片点击事件 productCards.forEach(card => { card.addEventListener("click", () => { const productData = { name: card.dataset.name, weight: card.dataset.weight, price: card.dataset.price }; openModal(card.dataset.modalTarget, productData); }); });
内容的提问来源于stack exchange,提问作者Alejandro Arango
相关产品推荐
相关产品推荐

