如何在同一页面上隔离不同的javascript库?

发布于 2024-10-02 06:48:47 字数 434 浏览 0 评论 0原文

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

这也不是 jquery 的问题 - 谷歌闭包库(甚至编译过)可以作为一个例子。

除了明显的 iframe 之外,还有哪些解决方案可以隔离不同的 javascript 库? 也许将 javascript 作为字符串加载,然后在匿名函数中使用 Function('code to eval'),而不是 eval('code to eval')) 进行 eval 可能会成功?

Suppose we need to embed a widget in third party page. This widget might use jquery for instance so widget carries a jquery library with itself.
Suppose third party page also uses jquery but a different version.
How to prevent clash between them when embedding widgets? jquery.noConflict is not an option because it's required to call this method for the first jquery library which is loaded in the page and this means that third party website should call it. The idea is that third party site should not amend or do anything aside putting tag with a src to the widget in order to use it.

Also this is not the problem with jquery in particular - google closure library (even compiled) might be taken as an example.

What solutions are exist to isolate different javascript libraries aside from obvious iframe?
Maybe loading javascript as string and then eval (by using Function('code to eval'), not the eval('code to eval')) it in anonymous function might do the trick?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

淡写薰衣草的香 2024-10-09 06:48:47

实际上,我认为 jQuery.noConflict 正是您想要使用的。如果我正确理解它的实现,你的代码应该看起来像这样:

(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$ 对象恢复为其之前的值。

Actually, I think jQuery.noConflict is precisely what you want to use. If I understand its implementation correctly, your code should look like this:

(function () {
var my$;

// your copy of the minified jQuery source

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

The call to noConflict will restore the global jQuery and $ objects to their former values.

一世旳自豪 2024-10-09 06:48:47

Function(...) 在你的函数中进行 eval,这并没有更好。

为什么不使用iframe,它们为第三方内容提供默认沙箱。

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

Function(...) makes an eval inside your function, it isn't any better.

Why not use the iframe they provide a default sandboxing for third party content.

And for friendly ones you can share text data, between them and your page, using parent.postMessage for modern browser or the window.name hack for the olders.

夜无邪 2024-10-09 06:48:47

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

该库名为 Packages JS,可以免费下载和使用,因为它是 Creative 下的开源代码共享许可证。

它基本上通过将代码封装在函数内来工作。从这些函数中,您可以导出想要公开给其他包的对象。在消费者包中,您将这些对象导入到本地名称空间中。如果其他人甚至您自己多次使用相同的名称也没关系,因为您可以解决歧义。

下面是一个示例:

(文件 example/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!";
  });
});

(文件 example/ambiguity.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);
});

(文件 example/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());
});

example/ambiguitytest.js 使用两个库,它们都导出一个函数再见,但它可以显式导入正确的函数并将它们分配给本地别名以消除它们之间的歧义。

以这种方式使用 jQuery 意味着“打包”jQuery,方法是将其代码包装在对 Package 的调用中,并导出它现在向全局范围公开的对象。这意味着对库进行一些更改,这可能不是您想要的,但可惜的是,如果不诉诸 iframe,我就无法看到这一点。

我计划在下载中包含流行库的“打包”版本,jQuery 肯定在列表中,但目前我只有 Sizzle(jQuery 的选择器引擎)的打包版本。

I built a library to solve this very problem. I am not sure if it will help you of course, because the code still has to be aware of the problem and use the library in the first place, so it will help only if you are able to change your code to use the library.

The library in question is called Packages JS and can be downloaded and used for free as it is Open Source under a Creative Commons license.

It basically works by packaging code inside functions. From those functions you export those objects you want to expose to other packages. In the consumer packages you import these objects into your local namespace. It doesn't matter if someone else or indeed even you yourself use the same name multiple times because you can resolve the ambiguity.

Here is an example:

(file example/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!";
  });
});

(file example/ambiguity.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);
});

(file example/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());
});

example/ambiguitytest.js uses two libraries that both export a function goodbye, but it can explicitly import the correct ones and assign them to local aliases to disambiguate between them.

To use jQuery in this way would mean 'packaging' jQuery by wrapping it's code in a call to Package and Exporting the objects that it now exposes to the global scope. It means changing the library a bit which may not be what you want but alas there is no way around that that I can see without resorting to iframes.

I am planning on including 'packaged' versions of popular libraries along in the download and jQuery is definitely on the list, but at the moment I only have a packaged version of Sizzle, jQuery's selector engine.

亽野灬性zι浪 2024-10-09 06:48:47

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

Instead of looking for methods like no conflict, you can very well call full URL of the Google API on jQuery so that it can work in the application.

∝单色的世界 2024-10-09 06:48:47
<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 和相关插件标签之后立即调用 jQuery.noConflict() 方法

  2. 存储结果 jquery到一个全局变量,其名称几乎不会发生冲突或混淆

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

  4. 接下来是你的逻辑代码。为了方便起见,使用闭包来获取私有 $。私有$不会与其他jquery冲突。

  5. 您最好不要忘记删除全局临时变量。
<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>

Most important points:

  1. call jQuery.noConflict() method IMMEDIATELY AFTER your own jquery and related plugins tags

  2. store the result jquery to a global variable, with a name that has little chance to conflict or confuse

  3. load your widget using the old versioned jquery;

  4. followed up is your logic codes. using a closure to obtain a private $ for convience. The private $ will not conflict with other jquerys.

  5. You'd better not forget to delete the global temp var.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文