You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用原生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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:40:27