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

jQuery动态ID绑定事件时弹窗fadeIn失效问题求助

问题分析与解决方案

你的问题出在JavaScript闭包的作用域陷阱上,下面我来详细拆解并给出修复方案:

核心问题原因

你在while循环中绑定点击事件时,事件处理函数引用的变量i是全局作用域下的同一个变量。当循环结束后,i的值已经变成了$maxcounter(也就是弹窗的总数),所以用户点击按钮时,代码会尝试查找#popup-$maxcounter——但你的弹窗ID是从0到$maxcounter-1,这个元素根本不存在,自然不会触发fadeIn效果。

先把你提供的代码还原为可读格式:

还原后的jQuery代码

$maxcounter = $('.testimonio-popup[id^="popup-"]').length; 
var i = 0; 
while (i < $maxcounter) { 
  $('#open-'+i).on('click', function() { 
    $('#popup-'+i).fadeIn('slow'); 
    $('.testimonio-overlay').fadeIn('slow'); 
    $('.testimonio-overlay').height($(window).height()); 
    return false; 
  }); 
  $('#close-'+i).on('click', function(){ 
    $('#popup-'+i).fadeOut('slow'); 
    $('.testimonio-overlay').fadeOut('slow'); 
    return false; 
  }); 
  i++; 
}

还原后的PHP代码

function get_the_content_with_formatting ($more_link_text = '(more...)', $stripteaser = 0, $more_file = '') { 
    $content = get_the_content($more_link_text, $stripteaser, $more_file); 
    $content = apply_filters('the_content', $content); 
    $content = str_replace(']]>', ']]&gt;', $content); 
    return $content; 
} 

add_shortcode( 'testimonios', 'display_testimonios' ); 

function display_testimonios($atts){ 
    $atributos = shortcode_atts([ 
        'grupo' => 'PORDEFECTO', 
    ], $atts); 

    $buffer = '<div class="testimonio-overlay"></div> '; 
    $contadorid = 0; 

    $q = new WP_Query(array( 
        'post_type' => 'test', 
        'tax_query' => array( 
            array( 
                'taxonomy' => 'grupos_testimonios', 
                'field' => 'slug', 
                'terms' => $atributos['grupo'] 
            ) 
        ) 
    )); 

    while ($q->have_posts()) { 
        $q->the_post(); 
        $buffer .= '<div class="testimonio">'; 
        $buffer .= '<div class="testimonio-img">' . get_the_post_thumbnail(get_the_ID()).'</div>'; // 修复:将$_post->ID改为get_the_ID()
        $buffer .= '<div class="testimonio-titulo"><p>' . get_the_title() .'</p></div>'; 
        $buffer .= '<div class="testimonio-intro"><div class="testimonio-parrafo">' . get_the_excerpt() . '</div><button class="testimonio-boton" id="open-'.$contadorid.'">Leer más</button></div></div>'; 
        $buffer .= '<div class="testimonio-popup" id="popup-'.$contadorid.'"><div class="testimonio-popup-contenido"><div class="testimonio-cerrar"><button class="testimonio-boton-cerrar" id="close-'.$contadorid.'">x</button></div>'; 
        $buffer .= '<div class="testimonio-popup-titulo"><p>' . get_the_title() .'</p></div>'; 
        $buffer .= '<div class="testimonio-popup-contenido">' . get_the_content_with_formatting() . '</div></div></div>'; 
        $contadorid++; 
    } 

    wp_reset_postdata(); 
    return $buffer; 
}

修复方案(三种可选)

方案1:使用ES6的let声明循环变量(最简单)

把循环变量i用let声明,这样每次循环都会创建一个独立的块级作用域,事件处理函数会绑定当前循环的i值:

const $maxcounter = $('.testimonio-popup[id^="popup-"]').length; 
// 换成for循环+let更清晰
for (let i = 0; i < $maxcounter; i++) { 
  $('#open-'+i).on('click', function() { 
    $('#popup-'+i).fadeIn('slow'); 
    $('.testimonio-overlay').fadeIn('slow').height($(window).height()); 
    return false; 
  }); 
  $('#close-'+i).on('click', function(){ 
    $('#popup-'+i).fadeOut('slow'); 
    $('.testimonio-overlay').fadeOut('slow'); 
    return false; 
  }); 
}

方案2:用闭包封装变量(兼容旧浏览器)

如果需要兼容不支持ES6的环境,用立即执行函数表达式(IIFE)把每个循环的索引封装起来:

const $maxcounter = $('.testimonio-popup[id^="popup-"]').length; 
var i = 0; 
while (i < $maxcounter) { 
  // 用IIFE捕获当前循环的索引
  (function(currentIndex) { 
    $('#open-'+currentIndex).on('click', function() { 
      $('#popup-'+currentIndex).fadeIn('slow'); 
      $('.testimonio-overlay').fadeIn('slow').height($(window).height()); 
      return false; 
    }); 
    $('#close-'+currentIndex).on('click', function(){ 
      $('#popup-'+currentIndex).fadeOut('slow'); 
      $('.testimonio-overlay').fadeOut('slow'); 
      return false; 
    }); 
  })(i); 
  i++; 
}

方案3:用data-*属性实现(最优雅推荐)

不需要依赖ID中的数字,给按钮添加data-target属性直接关联弹窗,代码更简洁且支持动态新增元素:

  1. 先修改PHP代码中的按钮部分:
// 打开按钮添加data-target属性
$buffer .= '<button class="testimonio-boton" id="open-'.$contadorid.'" data-target="#popup-'.$contadorid.'">Leer más</button>';

// 关闭按钮添加data-target属性
$buffer .= '<button class="testimonio-boton-cerrar" id="close-'.$contadorid.'" data-target="#popup-'.$contadorid.'">x</button>';
  1. 然后简化jQuery代码(使用事件委托更高效):
// 打开弹窗事件
$(document).on('click', '.testimonio-boton', function(e) {
  e.preventDefault();
  const targetPopup = $(this).data('target');
  $(targetPopup).fadeIn('slow');
  $('.testimonio-overlay').fadeIn('slow').height($(window).height());
});

// 关闭弹窗事件
$(document).on('click', '.testimonio-boton-cerrar', function(e) {
  e.preventDefault();
  const targetPopup = $(this).data('target');
  $(targetPopup).fadeOut('slow');
  $('.testimonio-overlay').fadeOut('slow');
});

额外小修复

你的PHP代码中get_the_post_thumbnail($_post->ID)可能存在未定义变量的问题,建议改为get_the_post_thumbnail(get_the_ID())——在$q->the_post()之后,get_the_ID()可以直接获取当前帖子的ID。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 17:42:40