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

后续点击事件触发错误href链接问题排查求助

外部链接离开提醒弹窗异常排查

问题现象

开发的外部链接提醒脚本,逻辑为:点击非白名单域名的外部链接时,触发「离开站点提醒」弹窗。首次点击功能正常,但后续点击其他外部链接时,弹窗虽能正常触发,但点击弹窗的「Okay」按钮后,会跳转到首次点击的链接,而非当前点击的目标链接。

提供的代码

jQuery控制代码(含Hubl注入)

$(window).on("load", function() {
  const popup   = $('.alert-popup-container');
  const domains = [];
  // populate whitelisted domains array - **fyi this is written in hubl**
  {% for item in module.domains %}
    domains.push("{{ item }}");
  {% endfor %}
  
  function confirm (link) {
    popup.addClass('active');

    $('.popup-cancle, .alert-popup-close').click(function(e){
      e.preventDefault();
      popup.removeClass('active');
      return true;
    });
    $('.popup-proceed').click(function(e){
      e.preventDefault();
      window.open(link, "_blank");
      popup.removeClass('active');
      return true;
    });
  }

  $('a').on('click', function(e){
    const target = $(this),
          href   = target.attr("href");

    var trigger_alert = true;

    // make sure url is not relative
    if (href.indexOf('://') !== -1) {
      for (var i = 0; i < domains.length; i++) {
        if (href.indexOf(domains[i]) != -1) {
          trigger_alert = false; // don't trigger the alert
        }
      }

      if (trigger_alert) {
        e.preventDefault();
        confirm(target.attr("href"));
      }
    }
  });
});

弹窗HTML代码

<div class="alert-popup-container">
  <div class="alert-popup">
    <div class="alert-popup-close"></div>
    {{ module.alert_text }}
     <div class='controls'>
       <div class="btn1">
         <a href="#" class='cta_button popup-proceed'>Okay</a>
       </div>
       <div class="btn2">
         <a href="#" class='cta_button popup-cancle'>Cancel</a>
       </div>
     </div>
  </div>
</div>

问题原因

核心问题是重复绑定点击事件:

  • 每次调用confirm()函数时,都会给弹窗的.popup-proceed、.popup-cancle等按钮绑定新的点击事件,旧的事件不会被覆盖,而是叠加在元素上。
  • 第一次点击链接时,confirm()绑定的事件闭包捕获了首次的link参数;后续点击其他链接时,新绑定的事件虽然携带了当前的link,但点击按钮时会优先执行最早绑定的事件,因此打开的始终是首次点击的链接。

修复方案

方案1:绑定前解绑旧事件

修改confirm()函数,在绑定新事件前,先解绑按钮上已存在的点击事件,避免事件叠加:

function confirm (link) {
  popup.addClass('active');

  // 先解绑所有旧的点击事件,再绑定新事件
  $('.popup-cancle, .alert-popup-close').off('click').click(function(e){
    e.preventDefault();
    popup.removeClass('active');
  });
  $('.popup-proceed').off('click').click(function(e){
    e.preventDefault();
    window.open(link, "_blank");
    popup.removeClass('active');
  });
}

方案2:事件委托(更优)

将弹窗按钮的点击事件只绑定一次到父容器,通过变量存储当前要跳转的链接,避免重复绑定问题:

$(window).on("load", function() {
  const popup   = $('.alert-popup-container');
  const domains = [];
  {% for item in module.domains %}
    domains.push("{{ item }}");
  {% endfor %}
  
  // 存储当前待跳转的链接
  let currentTargetLink = '';

  // 仅绑定一次弹窗按钮的事件
  $('.popup-cancle, .alert-popup-close').click(function(e){
    e.preventDefault();
    popup.removeClass('active');
    currentTargetLink = ''; // 清空存储的链接
  });
  $('.popup-proceed').click(function(e){
    e.preventDefault();
    if(currentTargetLink) {
      window.open(currentTargetLink, "_blank");
      currentTargetLink = '';
    }
    popup.removeClass('active');
  });

  $('a').on('click', function(e){
    const target = $(this),
          href   = target.attr("href");

    let trigger_alert = true;

    if (href.indexOf('://') !== -1) {
      for (let i = 0; i < domains.length; i++) {
        if (href.indexOf(domains[i]) !== -1) {
          trigger_alert = false;
          break; // 找到匹配域名后跳出循环,优化性能
        }
      }

      if (trigger_alert) {
        e.preventDefault();
        currentTargetLink = href; // 存储当前点击的链接
        popup.addClass('active');
      }
    }
  });
});

额外优化

在白名单域名检测的循环中,找到匹配域名后立即break,无需继续遍历,提升脚本执行效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 06:02:28