2010-11-12 44 views
13

假设我们需要在第三方页面中嵌入一个小部件。这个小部件可能使用jquery,所以小部件携带一个jquery库本身。 假设第三方页面也使用jquery,但版本不同。 如何在嵌入小部件时防止它们之间的冲突? jquery.noConflict不是一个选项,因为它需要调用此方法来加载页面中的第一个jquery库,这意味着第三方网站应该调用它。这个想法是,第三方网站不应该修改或做任何事情,除了把标签与src放到widget上以便使用它。如何在同一页面上分离不同的JavaScript库?

另外,这不是特别是jQuery的问题 - 谷歌封闭库(甚至编译)可能被视为一个例子。

除了明显的iframe之外,还存在哪些解决方案来隔离不同的JavaScript库? 也许加载JavaScript为字符串,然后eval(通过使用函数('代码eval'),而不是eval('代码eval'))它在匿名函数可能会做诡计?

+2

我不能强调一个想法'加载JavaScript作为字符串,然后评估它'多么糟糕'是,只是...不要,还有更多的原因不会这样做。 – 2010-11-12 12:59:56

+2

这是一个有趣的问题,在每个组件平台(DLL,COM,托管代码)中反复出现。这不是你的组件被破坏的情况,你需要更新它以工作到最新的libraries_。这是一个真正的问题,我想看看它将如何用动态语言来解决。 – Humberto 2010-11-12 13:07:36

+0

尼克,你是对的,但通过eval我的意思是使用Function('code to eval')实际上,而不是eval('code to eval')本身。我会更新我的问题。 – sha1dy 2010-11-12 13:11:57

回答

4

Function(...)在你的函数中做了一个评估,它并没有比这更好。

为什么不使用iframe他们提供了第三方内容的默认沙盒。

对于友好的用户,您可以在他们和您的页面之间共享文本数据,使用parent.postMessage用于现代浏览器或window.name用于老用户。

+1

是的,我会这样 - iframe沙箱我的js。 – sha1dy 2010-11-14 21:27:45

+1

吸框.. boooooo。我讨厌iframes。 'jQuery.noConflict(true);'是他需要的(对于第三方注入)iframe对于跨站点脚本来说是令人难以置信的头痛,而不是第三方插件创作的解决方案。 – ppumkin 2012-06-19 14:29:45

+0

@ppumkin这里的问题不是跨站点脚本或插件,而是相反,如何隔离JS代码。如果您有其他解决方案,请随时回答。 – Mic 2012-06-19 20:52:49

0

而不是寻找像没有冲突的方法,你可以很好地在jQuery上调用Google API的完整URL,以便它可以在应用程序中工作。

+0

并非总是如此 - 该应用程序可能会发布在公司内部网中,其中禁止访问Google API URL。 – Humberto 2010-11-12 13:40:22

+0

这并没有解决实际的问题,这两个版本都会尝试绑定到window。$和window.jQuery。 – lawnsea 2010-11-12 15:36:49

+0

他问没有冲突的代码,所以我给了这个想法。我不知道这是怎么回事它 – 2010-11-12 16:17:22

9

实际上,我认为jQuery.noConflict正是你想要使用的。如果我没有理解错的implementation,你的代码应该是这样的:

(function() { 
var my$; 

// your copy of the minified jQuery source 

my$ = jQuery.noConflict(true); 
// your widget code, which should use my$ instead of $ 
}()); 

noConflict呼叫将全球jQuery$对象还原到其以前的值。

+0

问题是如果第三个应用程序将使用noConflict加载jquery,并且该版本将与我期望使用的版本不兼容。 – sha1dy 2010-11-14 21:27:02

+0

其实,不,这不是问题,因为我绘制了解决方案。您的代码在匿名函数的范围内引用了my $变量(实际上可以命名为$)。第三个应用程序在该范围之外的更改不会对其值产生任何影响。 – lawnsea 2010-11-15 03:53:57

+0

+1这当然是处理这个问题的jQuery方式,但是重构所有你自己的代码很烦人。如果第三方脚本使用noConflict noConflict来确保与可能使用其代码的每个人的兼容性会更好。 – Muhd 2011-02-26 02:00:24

2

我建立了一个库来解决这个问题。我不确定它是否会对您有所帮助,因为代码仍然需要首先意识到问题并使用库,所以只有在您能够更改代码以使用库时才会有所帮助。

该图书馆被称为Packages JS,可以免费下载和使用,因为它是开源的创作共用许可证。

它基本上是通过在函数内部打包代码来工作的。从这些函数中导出要暴露给其他包的那些对象。在用户包中,您可以将这些对象导入到您的本地名称空间中。不管是否有人或甚至你自己多次使用相同的名字,因为你可以解决歧义。

下面是一个例子:

(例如文件/为greeting.js)

Package("example.greeting", function() { 
    // Create a function hello... 
    function hello() { 
    return "Hello world!"; 
    }; 

    // ...then export it for use by other packages 
    Export(hello); 

    // You need to supply a name for anonymous functions... 
    Export("goodbye", function() { 
    return "Goodbye cruel world!"; 
    }); 
}); 

(例如文件/歧义。JS)

Package("example.ambiguity", function() { 
    // functions hello and goodbye are also in example.greeting, making it ambiguous which 
    // one is intended when using the unqualified name. 
    function hello() { 
    return "Hello ambiguity!"; 
    }; 

    function goodbye() { 
    return "Goodbye ambiguity!"; 
    }; 

    // export for use by other packages 
    Export(hello); 
    Export(goodbye); 
}); 

(例如文件/ ambiguitytest.js)

Package("example.ambiguitytest", ["example.ambiguity", "example.greeting"], function(hello, log) { 
    // Which hello did we get? The one from example.ambiguity or from example.greeting? 
    log().info(hello()); 
    // We will get the first one found, so the one from example.ambiguity in this case. 

    // Use fully qualified names to resolve any ambiguities. 
    var goodbye1 = Import("example.greeting.goodbye"); 
    var goodbye2 = Import("example.ambiguity.goodbye"); 
    log().info(goodbye1()); 
    log().info(goodbye2()); 
}); 

例如/ ambiguitytest.js使用这两种导出功能再见两个库,但它可以明确地导入正确的参数并将它们分配给本地别名以消除它们之间的歧义。

以这种方式使用jQuery意味着'包装'jQuery通过将包装中的代码包装到打包和导出现在暴露给全局范围的对象中。这意味着改变图书馆有点可能不是你想要的,但唉,没有办法使用内联框架,我可以看到没有办法。

我打算在下载中包含流行库的“打包”版本,jQuery绝对在列表中,但目前我只有一个打包版本的Sizzle,jQuery的选择器引擎。

+0

看起来很有趣......但如果有人是noob并且注入一个插件代码形式,那么这个代码就不会真的很好。对于第三方,noconfilt是大多数情况下的最佳实践 – ppumkin 2012-06-19 14:28:33

+0

会有一种转发或处理第三方库的方法吗? – user831865 2016-04-17 13:20:37

+0

啊,你偶然发现了我的一个旧帖子。与此同时,我自己不再使用packages.js,同时它已被更好的解决方案所淘汰,如[RequireJS](http://requirejs.org/)。既然你提到了transpiling:现在我在ES6(它有原生的'import'和'export')编码,然后使用[Babel](https://babeljs.io/)和[的WebPack](https://webpack.github.io/)。 – 2016-04-17 16:40:15

0
<script src="myjquery.min.js"></script> 
<script>window.myjQuery = window.jQuery.noConflict();</script> 
... 
<script src='...'></script> //another widget using an old versioned jquery 
<script> 
(function($){ 
    //... 
    //now you can access your own jquery here, without conflict 
})(window.myjQuery); 
delete window.myjQuery; 
</script> 

最重要的几点:

  1. 调用jQuery.noConflict()方法会立即AFTER自己的jQuery和相关插件标签

  2. 店的结果jQuery的一个全局变量,用名称几乎没有机会冲突或混淆

  3. 使用旧版本的jquery加载您的小部件;

  4. 后续是您的逻辑代码。使用封闭来获得私人的便利。私人$不会与其他jquerys发生冲突。

  5. 您最好不要忘记删除全局临时变量。
相关问题