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

为何在函数内部添加overlay后无法绑定元素事件?

解决动态添加Overlay的事件绑定问题

要实现点击图片时动态创建Overlay、关闭时彻底移除,同时解决动态元素无法绑定事件的问题,核心是使用事件委托——将事件绑定到页面加载时就存在的静态元素(比如document),而非动态生成的元素本身。以下是修改后的完整代码及关键改动说明:

修改后的代码

/*
Gallery Fancybox
*/

var gallery = $('.item-detail__gallery'),
    galleryImgs = gallery.find('img'),
    galleryImgWrappers = gallery.find('a'),
    image = $('<img>', {class: 'lightbox__img'}),
    loadingImg = $('<img>', {src: '/bazar/assets/img/icons/circle.svg', class: 'loading-img'});

// Show overlay after click on a element of gallery
gallery.find('a').on('click', function(event) {
    event.preventDefault();

    // 动态创建Overlay并添加到body
    var overlay = $('<div id="overlay"><div id="overlay__left-arrow-block"><span id="overlay__left-arrow"></span></div><div id="top-margin"></div><div id="overlay__img-wrapper"></div><div id="overlay__bottom-slider"></div><div id="overlay__right-arrow-block"><span id="overlay__right-arrow"></span></div><div id="overlay__close-btn">Zavrieť</div></div>');
    overlay.appendTo('body');

    // Define variables
    var galleryImgWrapperHref = $(this).attr('href');

    // Show chosen image in overlay
    image.attr('src', galleryImgWrapperHref);

    // Show loading image before image is loaded
    loadingImg.appendTo(overlay.find('#overlay__img-wrapper')).show();

    // Image will show after it will be loaded, before loading image is showed
    image.on('load', function() {
        image.appendTo(overlay.find('#overlay__img-wrapper'));
        loadingImg.hide(); // Hide loading image after image was loaded
    });

    // Make images slider for thumbnails from gallery
    galleryImgs.each(function() {
        var src = $(this).attr('src'),
            href = $(this).parent().attr('href'),
            thumbWrapper = $('<a/>', {class: 'overlay__img-thumb-wrapper'}), // 替换id为class,避免重复ID问题
            thumbImg = $('<img>', {class: 'lightbox__img-thumb'});

        // Add thumb image src and href to a element from original element in gallery
        thumbWrapper.attr('href', href);
        thumbImg.attr('src', src);
        thumbWrapper.html(thumbImg); // Put image into thumbImgWrapper
        thumbWrapper.appendTo(overlay.find('#overlay__bottom-slider'));

        // If src of thumb and main image is the same then mark thumb as active
        if ((thumbImg.attr('src').substring(thumbImg.attr('src').lastIndexOf("/") + 1) == image.attr('src').substring(image.attr('src').lastIndexOf("/") + 1))) {
            thumbWrapper.addClass('img-active');
        }
    });
});

// 事件委托:点击底部缩略图切换图片
$(document).on('click','#overlay__bottom-slider a', function(event) {
    event.preventDefault();
    var overlay = $(this).closest('#overlay'),
        thumbWrapperHref = $(this).attr('href'),
        thumbWrapperCurrent = $(this);

    // Remove old active class and add on current element
    overlay.find('#overlay__bottom-slider').children().removeClass('img-active');
    thumbWrapperCurrent.addClass('img-active');

    // show loading img and hide old image
    loadingImg.show();
    image.hide();
    image.attr('src', thumbWrapperHref);

    // After new image will be loaded show it and hide loading image
    image.on('load', function() {
        loadingImg.hide();
       image.show();
    })
});

// 事件委托:点击图片容器关闭Overlay
$(document).on('click', '#overlay__img-wrapper', function()  {
    $(this).closest('#overlay').remove();
});

// 事件委托:点击关闭按钮移除Overlay
$(document).on('click', '#overlay__close-btn', function() {
    $(this).closest('#overlay').remove();
});

// 按ESC键移除Overlay
$(document).on('keyup',function(event) {
    if (event.which == 27) $('#overlay').remove();
});

// 事件委托:点击左箭头切换图片
$(document).on('click', '#overlay__left-arrow-block', function() {
    var overlay = $(this).closest('#overlay'),
        bottomSlider = overlay.find('#overlay__bottom-slider'),
        thumbWrapper = bottomSlider.find('.img-active');

    let prevImageSrc, targetThumb;
    // Action if it is first thumbWrapper - next wrapper is last one
    if (thumbWrapper.is(':first-child')) {
        targetThumb = bottomSlider.children().last();
        prevImageSrc = targetThumb.attr('href');
    } else {
        targetThumb = thumbWrapper.prev();
        prevImageSrc = targetThumb.attr('href');
    }

    // 更新active状态
    thumbWrapper.removeClass('img-active');
    targetThumb.addClass('img-active');

    // show loading img and hide old image
    loadingImg.show();
    image.hide();
    image.attr('src', prevImageSrc);

    // After new image will be loaded show it and hide loading image
    image.on('load', function() {
        loadingImg.hide();
        image.show();
    });
});

// 补充右箭头事件(原代码遗漏)
$(document).on('click', '#overlay__right-arrow-block', function() {
    var overlay = $(this).closest('#overlay'),
        bottomSlider = overlay.find('#overlay__bottom-slider'),
        thumbWrapper = bottomSlider.find('.img-active');

    let nextImageSrc, targetThumb;
    // Action if it is last thumbWrapper - next wrapper is first one
    if (thumbWrapper.is(':last-child')) {
        targetThumb = bottomSlider.children().first();
        nextImageSrc = targetThumb.attr('href');
    } else {
        targetThumb = thumbWrapper.next();
        nextImageSrc = targetThumb.attr('href');
    }

    // 更新active状态
    thumbWrapper.removeClass('img-active');
    targetThumb.addClass('img-active');

    // show loading img and hide old image
    loadingImg.show();
    image.hide();
    image.attr('src', nextImageSrc);

    // After new image will be loaded show it and hide loading image
    image.on('load', function() {
        loadingImg.hide();
        image.show();
    });
});

关键改动说明

  1. 动态创建Overlay:将Overlay的创建逻辑移到图片点击事件内部,每次点击生成全新的Overlay实例,避免复用旧元素导致的状态混乱。
  2. 事件委托绑定:所有针对Overlay内部元素的事件(关闭按钮、左右箭头、缩略图等),都通过$(document).on()绑定到document,确保动态生成的元素能触发事件。
  3. 彻底移除Overlay:所有关闭操作(点击关闭按钮、图片容器、ESC键)都使用remove()而非hide(),彻底从DOM中移除元素,释放资源。
  4. 修复重复ID问题:将缩略图容器的id="overlay__img-thumb-wrapper"改为class="overlay__img-thumb-wrapper",避免多次创建Overlay时出现重复ID的DOM问题。
  5. 补充右箭头事件:原代码中遗漏了右箭头的点击逻辑,补上完整的切换功能。

内容的提问来源于stack exchange,提问作者Dump

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:00:47