如何在 replaceWith 之后重新绑定 jQuery 事件处理程序,例如在使用 Optimizely 时

How to rebind jQuery event handlers after replaceWith, e.g when using Optimizely

本文关键字:程序 事件处理 Optimizely jQuery 绑定 之后 replaceWith 新绑定      更新时间:2023-09-26

优化 A/B 测试服务广泛使用.replaceWith("new HTML")来生成简单的 A/B 测试。这会产生从替换元素中删除侦听事件的任何事件侦听器的副作用,即使新元素具有相同的 ID/类也是如此。

例:

  1. DOM 包含:

    <div class="something">
      <button id="myButton"></button>
    </div>
    
  2. 已听: $("#myButton").click(function() { console.log('clicked!'); });

  3. 替换为: $(".something").replaceWith("some new HTML, containing #myButton");

在第 3 步之后,点击 #myButton 不再起作用,因为原始 DOM 元素已被销毁并添加了一个新的元素。

解决这个问题的好方法和"干净"的方法是什么?

可能的解决方案

  1. 了解您的代码库并在 Optimizely 的实验中"重新添加"适当的事件侦听器。
    • 问题:A/B测试人员可能不是真正的软件开发人员,认为这很麻烦。
    • 似乎不是一个很干净的方式
  2. 找到一种在 Optimizely 之后执行代码的方法,以这种方式添加所有事件侦听器。有没有好方法可以做到这一点?

  3. 使用"使用 $.on() 的事件委托",如下所述:如何用 jQuery 替换 HTML 但保留事件绑定

    • 问题:很难预测究竟会测试和替换 A/B
    • 的内容

编辑:我正在使用jQuery 1.11.x

我不确定是否有一种"干净"的方法可以做到这一点,因为附加到旧元素的事件可能不适用于新元素。想象一下,一个表单元素被div 替换:onchangeonblur事件应该发生什么?

优化尝试同时迎合两种不同类型的用户:高级用户和新手。所见即所得不能做复杂的变化,所以如果你正在编辑代码,那么你应该知道你在做什么。

一般而言,这意味着上面的选项1。两种合理的方法是:

  1. 将旧元素转换为新元素,而不仅仅是替换它
  2. 隐藏旧元素,
  3. 添加新元素,然后将事件从新元素代理到旧元素

当然,除非主代码库将事件与事件委托绑定,在这种情况下,保持相同的 ID/类就足够了。如果您可以访问原始代码库(对于在 Optimizely 编辑器中工作的人来说,情况通常并非如此 - 我为最大的第三方测试机构工作,我们无法对客户的实际代码库进行任何更改),那么无论如何您都应该升级到事件委派。

如果您有权访问主站点代码,那么您当然可以创建一个附加到窗口的回调(Optimizely 作用域它的所有代码),您的 Optimizely 代码在完成后调用该回调,但同样,事件委派可能是一个更好的选择。

当你说你正在使用jQuery 1.11.x时,你是指在你的网站上,还是Optimizely包含什么?如果 Optimizely 包含什么,它是修剪版本还是完整版本(优化项目主页-->设置-->Javascript)?

你不应该使用 jQuery 的 onRemove() 来首先为 Optimizely 的"魔术"后面发生的事件设置侦听器,例如2200494?