1

我正在尝试将 jQuery 作为 YUI 模块加载,而不将其添加到全局范围。

我想出的最好的方法是创建一个全局的module.exports,以便 jQuery 认为它是一个通用的 js 模式,并且不创建一个全局的 jQuery 对象......

// must create global object for jQuery to detect and attach to
// otherwise it will create itself in the global scope
module = {
    exports: {}
};

YUI({
    modules: {
        'my-jquery': {
            fullpath: '//cdnjs.cloudflare.com/ajax/libs/jquery/1.10.1/jquery.min.js',
            requires: [
                'node']
        }
    },
    onProgress: function (e) {
        switch (e.name) {
            case 'my-jquery':
                (function () {

                    var clone;

                    YUI.add('my-jquery', function (Y) {

                        if (!clone) {
                            clone = Y.clone(module.exports, true);
                            module.exports = {};
                        }

                        Y.namespace('my').jQuery = clone;

                    }, '1.10.1', {
                        requires: [
                            'node']
                    });

                })();
                break;
        }
    }

}).use('my-jquery', function (Y) {

    console.log('before');
    var jQuery = $ = Y.my.jQuery;
    console.log('walks');

    // regular old jQuery stuff here...
    $('#main').hide();

    // no global jQuery object
    console.log(1, window.jQuery);

    // there is a local jQuery object
    console.log(2, jQuery);

})

演示:http: //jsfiddle.net/syvGZ/2/

有没有更好的方法在 YUI 中加载 jQuery 而无需触及全局范围?

4

1 回答 1

1

您使用 using 走在正确的轨道上onProgress,但您不需要跳过克隆和伪造的所有环节module.exports。诀窍是使用jQuery.noConflict().

jQuery.noConflict做两件事:

  • 它返回 jQuery 函数
  • 如果它存在,它将恢复以前版本的 jQuery,或者从全局对象中删除 jQuery

这是它如何工作的说明:

<script src="jquery.1.8.js"></script>
<script>
var jQuery18 = jQuery;
</script>
<script src="jquery.1.9.js"></script>
<script>
// the true parameter makes this work for both the $ and jQuery global variables, not just the $
var jQuery19 = jQuery.noConflict(true);
alert('is the global jQuery is jQuery19? ' + (jQuery === jQuery19)); // false
alert('is jQuery19 the same as jQuery18? ' + (jQuery19 === jQuery19)); // false
alert('is the global jQuery the same as jQuery18? ' + (jQuery === jQuery18)); // true
</script>

另一个问题是,由于 YUI 需要具有串联模块的脚本,e.name因此不引用模块的名称,而是引用刚刚加载的脚本的 URL。该脚本中加载的模块的名称可以在e.data. 这只是意味着您需要迭代e.data以确定是否加载了 jQuery。

总而言之,您的脚本应如下所示:

YUI({
  modules: {
    'jquery': {
      fullpath: '//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js'
    }
  },
  onProgress: function (e) {
    for (var _module, i = 0, length = e.data.length; i < length; i++) {
      _module = e.data[i];
      if (_module.name === 'jquery') {
        // trap jQuery here while removing it from the global object
        (function ($) {
          YUI.add('jquery', function (Y) {
            Y.jQuery = $;
          });
        }(jQuery.noConflict(true)));
      }
    }
  }
}).use('jquery', function (Y) {
  var $ = Y.jQuery;
  $('foo').attr('bar', 'baz');
});

如果包含插件的脚本假定 jQuery 位于全局对象中(大多数情况下),插件可能会成为问题。所以我建议你自己托管它们并将它们包装在YUI.add.

于 2013-06-29T21:39:24.150 回答