You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

多图片点击弹窗功能的JavaScript代码优化咨询

多图片点击弹窗功能的JavaScript代码优化咨询

我做了一个图片弹窗功能,用JavaScript实现onClick触发不同图片的弹窗。

HTML代码片段

<img onmouseover="imgload();" src="11.jpg">
<img onmouseover="imgbarb();" src="13.jpg">

JavaScript代码现状

我用下面的JavaScript来实现onmouseover对应的函数,每个图片都要写一个单独的函数:

对应11.jpg的函数

function imgload() {
  var imgContainers   = document.querySelectorAll('.img-container');
  var tooltipElements = document.querySelectorAll('.tooltip');
  var popup           = document.getElementById('imagePopup1');
  var popupOverlay    = document.getElementById('imagePopupOverlay1');
  var popupImage      = document.getElementById('popupImage1');
  var closePopupBtn   = document.getElementById('closeImagePopupBtn1');
  // Show tooltip on hover
  imgContainers.forEach((container, index) => {
    var tooltip = container.querySelector('.tooltip');
    var image   = container.querySelector('img');
    container.addEventListener('mouseenter', function() {
      tooltip.style.display = 'block';
    });
    container.addEventListener('mouseleave', function() {
      tooltip.style.display = 'none';
    });
    // Open full-size image popup when image is clicked
    image.addEventListener('click', function() {
      var imageSrc               = "11-new.jpg";
      popupImage.src             = imageSrc;
      popup.style.display        = 'block';
      popupOverlay.style.display = 'block';
    });
  });
  // Close the image popup when clicking the close button
  closePopupBtn.addEventListener('click', function() {
    popup.style.display        = 'none';
    popupOverlay.style.display = 'none';
  });
  // Close the image popup when clicking the overlay
  popupOverlay.addEventListener('click', function() {
    popup.style.display        = 'none';
    popupOverlay.style.display = 'none';
  });
}

对应13.jpg的函数

function imgbarb() {
  var imgContainers   = document.querySelectorAll('.img-container');
  var tooltipElements = document.querySelectorAll('.tooltip');
  var popup           = document.getElementById('imagePopup1');
  var popupOverlay    = document.getElementById('imagePopupOverlay1');
  var popupImage      = document.getElementById('popupImage1');
  var closePopupBtn   = document.getElementById('closeImagePopupBtn1');
  // Show tooltip on hover
  imgContainers.forEach((container, index) => {
    var tooltip = container.querySelector('.tooltip');
    var image   = container.querySelector('img');
    container.addEventListener('mouseenter', function() {
      tooltip.style.display = 'block';
    });
    container.addEventListener('mouseleave', function() {
      tooltip.style.display = 'none';
    });
    // Open full-size image popup when image is clicked
    image.addEventListener('click', function() {
      var imageSrc               = "13-new.jpg";
      popupImage.src             = imageSrc;
      popup.style.display        = 'block';
      popupOverlay.style.display = 'block';
    });
  });
  // Close the image popup when clicking the close button
  closePopupBtn.addEventListener('click', function() {
    popup.style.display        = 'none';
    popupOverlay.style.display = 'none';
  });
  // Close the image popup when clicking the overlay
  popupOverlay.addEventListener('click', function() {
    popup.style.display        = 'none';
    popupOverlay.style.display = 'none';
  });
}

现在我有30多张图片,每张图都要新建一个函数,还要在HTML里加对应的onmouseover调用,不仅麻烦还让代码变得臃肿。我试过用ifelse和数组,但都没成功,想问问有没有更简洁的方法,不用每次加新图都写新函数?


嗨,我来帮你解决这个重复代码的问题!其实核心思路是把重复的逻辑抽离出来,让数据(也就是图片的对应关系)和逻辑分开,这样不管加多少张图,都不用改JavaScript代码,只要改HTML就行。

第一步:优化HTML结构

首先,我们给每个图片元素加一个自定义属性,比如data-popup-src,用来存点击后要弹窗显示的大图地址,这样就不用在函数里硬编码11-new.jpg这种路径了。另外,把onmouseover去掉,换成页面加载时统一绑定事件,这样更规范:

<!-- 假设每个图片都放在.img-container里,和你原来的结构对应 -->
<div class="img-container">
  <img src="11.jpg" data-popup-src="11-new.jpg" alt="图片11">
  <div class="tooltip">查看大图</div>
</div>
<div class="img-container">
  <img src="13.jpg" data-popup-src="13-new.jpg" alt="图片13">
  <div class="tooltip">查看大图</div>
</div>
<!-- 弹窗的结构保持不变,还是你原来的那些元素 -->
<div id="imagePopup1" style="display:none;">
  <span id="closeImagePopupBtn1">&times;</span>
  <img id="popupImage1" src="">
</div>
<div id="imagePopupOverlay1" style="display:none;"></div>

第二步:重构JavaScript代码

现在我们只需要写一次初始化代码,页面加载完成后,统一给所有图片绑定提示框和弹窗事件,不用每个图片写单独的函数:

// 页面加载完成后执行初始化
document.addEventListener('DOMContentLoaded', function() {
  // 先获取弹窗相关的元素,只获取一次就行,不用每次函数都重新拿
  const popup = document.getElementById('imagePopup1');
  const popupOverlay = document.getElementById('imagePopupOverlay1');
  const popupImage = document.getElementById('popupImage1');
  const closePopupBtn = document.getElementById('closeImagePopupBtn1');

  // 绑定关闭弹窗的事件,同样只绑一次
  function closePopup() {
    popup.style.display = 'none';
    popupOverlay.style.display = 'none';
  }
  closePopupBtn.addEventListener('click', closePopup);
  popupOverlay.addEventListener('click', closePopup);

  // 处理所有图片容器的提示框和点击弹窗逻辑
  const imgContainers = document.querySelectorAll('.img-container');
  imgContainers.forEach(container => {
    const tooltip = container.querySelector('.tooltip');
    const image = container.querySelector('img');

    // 提示框的显示/隐藏
    container.addEventListener('mouseenter', () => {
      tooltip.style.display = 'block';
    });
    container.addEventListener('mouseleave', () => {
      tooltip.style.display = 'none';
    });

    // 点击图片打开弹窗
    image.addEventListener('click', () => {
      // 从自定义属性里拿大图地址
      const largeImageSrc = image.dataset.popupSrc;
      popupImage.src = largeImageSrc;
      popup.style.display = 'block';
      popupOverlay.style.display = 'block';
    });
  });
});

为什么这样做更优?

  1. 不用重复写函数:不管你加10张还是50张图,只要在HTML的<img>标签里加好data-popup-src属性,JavaScript代码完全不用改。
  2. 代码更简洁:原来重复的关闭弹窗逻辑、提示框逻辑都只写了一次,减少了冗余。
  3. 更易维护:图片的原图和大图对应关系直接写在HTML里,一目了然,后期修改路径也不用动JS。

额外的小优化

如果你的大图命名有规律(比如都是原图文件名-new.jpg),甚至连data-popup-src都可以不用加,直接在JS里通过原图的src来生成大图地址,比如:

// 假设原图是11.jpg,大图是11-new.jpg
const originalSrc = image.src;
const largeImageSrc = originalSrc.replace('.jpg', '-new.jpg');

这样HTML里连自定义属性都省了,更省心!

如果之前用数组没成功,可能是因为没有把事件绑定的逻辑和数据对应起来,现在这种方式把所有逻辑都统一初始化,数据存在HTML的属性里,就完美解决了重复代码的问题啦~


备注:内容来源于stack exchange,提问作者Nitesh

火山引擎 最新活动