【问题标题】:Ninja Kill a Rogue JavaScript EventNinja Kill a Rogue JavaScript 事件
【发布时间】:2014-01-21 22:23:05
【问题描述】:

所以这是情节,这是一个真实的故事(一个真实的人存在的问题,即 - 我):

您在一个大型企业网站上工作,其中包含大量 JavaScript,特别是 jQuery 代码,您无法控制,也无法更改(祝您好运,即使找出是谁编写的,或者为什么编写) .涉及到认证和权限的层级,所以就假装它是一成不变的,你不能碰它。

在这段代码的某处,有一个事件在文档加载后将其滚动到页面顶部。 “好吧,这听起来无害”可能有人会想 - 但现在您的任务是根据查询字符串或锚点将页面滚动到特定项目。

通常一切正常,但是当您单击指向 example.com/list#item11 的链接时,浏览器会按预期工作,然后您会直接转到要链接的项目...然后,whammo ,页面立即跳回页面顶部。

现在,您可能会说“好吧,这就是 document.ready() 的用途!”...令您惊恐的是,您发现流氓事件无论如何都会发生。

在 StackOverflow 搜索要关联的更晚的事件后,您会发现这个宝石:

$(document).ready(function(e) {
  $(window).load(function(e){ });
}

当然,这肯定会奏效!只是,它没有。你试试return falsee.preventDefault(),但这对你没有用。

您可以确定的是,这个恶意滚动事件发生在您的代码运行之后、DOM 准备好之后,并且肯定是在 window.load() 事件之后。你确定没有别的。

你能刺杀这个流氓事件吗?是否有一些机制可以拦截滚动事件并防止它们发生?你可以链接到一些事件后面的事件,比如“DOM 准备好,窗口加载,页面设置好了,孩子们上床睡觉了,所有其他事件都已经处理完毕......event()”?

我现在能想到的唯一解决方案是“放弃 - 页面加载时的滚动行为在您的场景中不起作用”,“使用计时器并等待!然后提交 seppuku,因为它是一个如此肮脏的黑客!”,和“忍者暗杀任务!” (因为我不知道谁写了有问题的代码,我不得不满足于杀死他们的代码而不是他们——我相信他们有他们的理由,或者已经被暗杀......或者至少在等待要传递的代码并做我的事)。

是否有一些更好的方法,一些难以找到的功能,一些最后的手段来调用奥术黑暗魔王的反射,或者是时候放弃并以另一种方式解决问题?

TLDR;

1) 当您无法更改导致它的代码时,如何阻止破坏性脚本事件(如滚动)的发生?可接受的答案包括如何确保您的代码在之后运行 - 不使用计时器黑客! - 和/或如果您的代码总是先运行,您如何防止后面的代码弄乱您的代码?

2) 了解事件是如何定义的以及触发了哪些事件可能会有所帮助,但我认为这是一个单独的问题,可能不一定需要解决这种情况。出于说明目的,假设有数千个活动事件和侦听器分布在数十个缩小的脚本文件中。可能很难确定到底发生了什么,甚至尝试都太麻烦了。

【问题讨论】:

  • 有几个删除事件处理程序,如unbind, off, undelegate。不过,在空手道之前,您可能需要确切地知道它是如何添加或运行的。
  • @Fraser 这个问题比你的建议更具体...
  • @Rob W - 不要投票关闭。这是同一个问题,但只是使用华丽的语言来描述定位何时/何处触发事件的简单问题。
  • 为什么用 50 个字,而 500 个字就行了?

标签: javascript jquery javascript-events


【解决方案1】:

最好的解决方案是编辑声明就绪事件的源代码。

如果不能,您可以将此代码复制到其他地方并进行编辑。

如果完全不可能,那么

您不能取消绑定就绪事件,因为这可能会导致问题。

您可以通过其原型覆盖 window.scrollTop() 函数

window.prototype.scrollTo2 = window.prototype.scrollTo;
window.prototype.scrollTo = function(){

  /*Look in the url if you have an hash tab*/
  // if yes return false
  //if not 
  window.prototype.scrollTo2()
};

【讨论】:

  • 这正是我认为可能但甚至认为不可能的事情。 +1 仅此一项!这也突出了找出可能导致该行为的事件类型的重要性,因为如果它确实是 scrollTo() 这确实会以非常有针对性的方式彻底杀死它! “我会处理这个页面的滚动条事件,谢谢——不要碰!”
  • 可悲的是,我试过:'window.scrollTo = function(){ return false; }; window.scrollBy = function(){ return false; }; window.scrollByLines = function(){ return false; }; window.scrollByPages = function(){ return false; }; window.prototype.scrollTo = function(){ return false; }; window.prototype.scrollBy = function(){ return false; }; window.prototype.scrollByLines = function(){ return false; }; window.prototype.scrollByPages = function(){ return false; }; ',一切都无济于事。在控制台中,这根本不会改变行为:(
  • 更改原型函数而不是函数本身t
  • 我都试过了,只是以防万一,但都没有。我怀疑这是一个浏览器安全功能,我似乎根本无法覆盖该功能。
  • 有跳转到顶部的js链接吗,我想看看
【解决方案2】:

如果一切都失败了,用计时器打他们:

$(document).ready(function() {
    window.setTimeout(function() {
        document.location = "#bottom";
    }, 200);
});

Live test case.

丑陋,但工作。

【讨论】:

  • 它确实有效,但这正是我希望避免的丑陋 :( 这当然是最简单的,甚至可能是最好的——我只是明确地(在问题中)想要寻找不同的方式。
  • @BrianDHall 希望我有更好的答案,但就目前而言,没有真正的方法来捕获滚动回顶部并杀死它的特定代码。
  • 您可能是对的,这可能确实是唯一真正有效的(如果不愉快的话)解决方案。无论如何,这实际上可能是真正以最小的副作用解决问题的唯一方法!但是,我们确实会看到:)
【解决方案3】:

我会钩入 window.scrollTo 原型,以尝试在行为中抓住窃贼。如果你知道它是怎么做的,那就更容易摆脱它了。

如果这个流氓调用没有嵌入到太多的 JQuery goo 中,它甚至可以追踪到原来的罪魁祸首,他很快就会被极大的报复和愤怒所击倒。

【讨论】:

  • 确实,这绝对是一个很好的线索。如果对情况有帮助,我会报告! +1
猜你喜欢
  • 1970-01-01
  • 2014-06-11
  • 2011-04-09
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
相关资源
最近更新 更多