RequireJS'ing 一个没有全局 $ 变量的 jQuery 插件

RequireJS'ing a jQuery plugin without a global $ variable

我不知道这是否可行,但我正在尝试开发一个在 [=51= 中加载时不会创建全局 $jQuery 变量的应用程序],但仍然适用于一些并非为 AMD 开发的插件。

主脚本

require.config({
    baseUrl: '/js/lib',
    paths: {
        jquery: 'vendor/jquery-2.1.3.min',
        somePlugin: 'vendor/somePlugin.min'
    },
    map: {
        '*': { jquery: 'secret-jquery' },
        'secret-jquery': { jquery: 'jquery' }
    },
    shim: {
        somePlugin: ['jquery']
    }
});

秘密-jquery.js

define(['jquery'], function (jQuery) {
    return jQuery.noConflict(true);
});

不幸的是,它设置 jQuery 插件如下:

somePlugin.min.js

$.fn.somePlugin = function (options) {
    // ...
});

如果我将插件源更改为使用 define,则不需要 shim,即

define(['jquery'], function ($) {
    $.fn.somePlugin = function (options) {
        // ...
    });
});

但这打破了不修改第三方插件的规则,尤其是流行的插件,我以后可能会用更新的版本换掉它们。

不能使用全局$jQuery变量,因为我的脚本需要将jQuery注入到可能已经有的页面上加载了它(并因此加载了一个不兼容 API 的不同版本,而我的 jQuery 无法破坏页面上的任何内容)。

有没有一种干净的方法来做到这一点,或者是只更改插件代码的最佳方法?我想不出任何其他方法,通过 XMLHttpRequest 在脚本中保存加载,用 define 调用包装它,然后 evaling 它,这似乎会打败让 RequireJS 处理脏工作的目的。

我们这样做的方式是定义我们的秘密-jquery.js 像这样:

define(['jquery', 'vendor/somePlugin.min'], function (jQuery) {
    return jQuery.noConflict(true);
});

我们的配置如下:

require.config({
    baseUrl: '/js/lib',
    paths: {
        jquery: 'vendor/jquery-2.1.3.min',
        somePlugin: 'vendor/somePlugin.min'
    },
    map: {
        '*': { jquery: 'secret-jquery' },
        'secret-jquery': { jquery: 'vendor/jquery-2.1.3.min' }
    },
    shim: {
        somePlugin: ['jquery']
    }
});

这使我们使用 jQuery 不使用 RequireJS 的插件的问题最少,同时仍然允许我们在自己的代码中利用 RequireJS。当然,我们不会跟踪一段代码使用了哪些 jQuery 插件,但在我看来,通常开发 jQuery 插件并不是为了让这一切变得简单,因为即使它们能够使用 RequireJS,它们通常不会 return 任何东西,而是扩展 jQuery 本身。