奇怪的 Chrome 原型/jQuery 冲突

Posted

技术标签:

【中文标题】奇怪的 Chrome 原型/jQuery 冲突【英文标题】:Weird Chrome prototype/jQuery conflict 【发布时间】:2010-10-24 10:46:51 【问题描述】:

我们有一个带有依赖原型的遗留代码的应用程序,但我们发现它对于我们想要使用它的大多数地方来说过于“繁重”,并且发现 jQuery 更适合我们的方式工作。所以我们正在迁移到 jQuery 以获得新功能。

与此同时,我们有几个页面需要加载这两个库:

<script language="javascript" type="text/javascript"
        src="prototype-1.5.1.2.js"></script> 
<script language="javascript" type="text/javascript"  
        src="jquery-1.3.2.js"></script> 
<script language="javascript" type="text/javascript">
    $j = jQuery.noConflict();
</script> 

(请注意旧版本的原型,我们在升级时发现了我们不想在逐步淘汰它时修复的问题)

这适用于 IE6、IE7、IE8-as-7 和 FX3,但在 Chrome 中加载它并且所有 jQuery 的东西都失败了。

加载开发者 javascript 控制台显示以下错误:

Uncaught Error: NOT_SUPPORTED_ERR: DOM Exception 9 http://.../prototype-1.5.1.2.js (line 1272)
Uncaught TypeError: Object #<an Object> has no method 'ready' http://.../lib.js (line 161)
Uncaught TypeError: Object #<an Object> has no method 'slideUp' http://.../page.aspx (line 173)
... and so on - all the failures are missing jQuery methods

所以这看起来像是原型中的冲突,导致 jQuery 对象的创建失败。

具体的原型问题似乎是 Prototype.BrowserFeatures.XPath 不正确,因为不支持 XPath document.evaluate。

好的,现在在打开 javascript 控制台的情况下重新加载页面 - 一切正常! WTF?关闭控制台,重新加载,再次失败。

只有在没有打开 javascript 控制台的情况下发生页面加载时才会发生故障 - 为什么会有任何不同?这看起来很像 Chrome 中的错误。

谁能解释发生了什么问题?为什么原型中的错误会导致 jQuery init 失败?为什么在打开控制台的情况下加载页面可以正常工作?

有人知道一个好的解决方法吗? (除了升级到prototype-1.6.0.3.js,它修复了这个问题,但在其他地方打破了遗留代码的负载)

【问题讨论】:

【参考方案1】:

来自Core/jQuery.noConflict:

注意:此函数必须在包含 jQuery javascript 文件之后调用,但之前包括任何其他冲突库,并且在实际使用其他冲突库之前,以防最后包含 jQuery。可以在 jQuery.js 文件的末尾调用 noConflict 来全局禁用 $() jQuery 别名。 jQuery.noConflict 返回一个对 jQuery 的引用,所以它可以用来覆盖 jQuery 对象的 $() 别名。

也许尝试将其更改为:

<script language="javascript" type="text/javascript"
  src="jquery-1.3.2.js"></script> 
<script language="javascript" type="text/javascript">
    $j = jQuery.noConflict();
</script>
<script language="javascript" type="text/javascript"
  src="prototype-1.5.1.2.js"></script>

【讨论】:

这行得通,谢谢。知道为什么 Chrome 控制台也会修复它吗? 使用任何一种调试工具(尤其是浏览器内的 JavaScript 工具)都会导致代码以不同的方式执行,“我们观察到的不是自然本身,而是暴露给我们提问方法的自然。” (海森堡,物理学和哲学,1963 年)。另外,别忘了接受我的回答! +1 这对我也有帮助。我想指出有冲突的文档让我小心:docs.jquery.com/Using_jQuery_with_Other_Libraries 情况并非总是如此,而且很多时候您无法控制页面中的脚本,比如说,如果您制作了用户添加到其网站/博客的某种第 3 方服务。 【参考方案2】:

我发现这个问题的根源是:

    Prototype 加载,由于 WebKit 缺少 document.getElementsByClass(),Prototype(偷偷地)创建了它。

    jQuery 初始化开始,在最顶部,它将window.$ 设置为jQuery

    在 JQuery 初始化期间,Sizzle 引擎(在 1.3.2 中添加?)初始化。作为自省的一部分,它会检查并测试document.getElementsByClass() 的功能。结果,它调用了Prototype对getElementsByClass()的实现,这取决于window.$被设置为Prototype的$,而不是jQuery的。

最终,这需要在 jQuery 中修复(请参阅票证 http://bugs.jquery.com/ticket/4365 和 5027)。我的快速补丁是在 jQuery 的初始化顶部删除对 window.$ 的分配。

【讨论】:

确实是这个问题。正如票中提到的那样,有一个部分可以包含在 try/catch 中,所以绕过这个。

以上是关于奇怪的 Chrome 原型/jQuery 冲突的主要内容,如果未能解决你的问题,请参考以下文章

jQuery库冲突

jQuery 和原型冲突

jQuery与原型脚本冲突

如何在我的 Jquery 中删除冲突?

不同版本jq冲突问题

jQuery:仅针对 Safari