在noConflict模式下使用jQuery在require.js中加载非AMD兼容的jQuery插件的正确方法?

时间:2013-01-07 04:26:08

标签: requirejs amd

假设我想将jquery与使用标准闭包定义的标准的非amd启用的jquery插件一起使用:(function($))( $.fn.myplugin = { ... } )(jQuery);并且它们都位于js/libs/jquery/jquery.myplugin.js内。

我使用此配置:

require.config({
  baseUrl: 'js/',
  paths: {
    'jquery':          'libs/jquery/jquery-noconflict', 
    'underscore':      'libs/underscore/underscore',
    'backbone':        'libs/backbone/backbone',
    'jquery-myplugin': 'libs/jquery/jquery.myplugin'
  },
  shim: {
    'backbone': {
      deps: ['underscore', 'jquery'],
      exports: 'Backbone'
  },
  'jquery-myplugin': {
    deps:  ['jquery'] 
  }
});

我在libs/jquery/jquery-noconflict.js中以无冲突模式加载jQuery,因为我不想污染全局命名空间:

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

这就是我加载主app.js的方式:

define([
  'jquery',
  'underscore',
  'backbone',
  'jquery-myplugin'],
function($, _, Backbone, MyPlugin){
  //MyPlugin is always undefined, not even sure if 
  //I should be passing it here if it only extends jQuery?
});

现在,这是我遇到的问题 - 虽然我可以使用上面定义的所有库而没有任何问题,但我无法找到正确的shim配置来加载非AMD启用的jquery插件。

我已尝试将jquery-myplugin设置为deps的{​​{1}}(以及其他方式)但我永远无法让它正常工作。

似乎我遇到以下情况的问题:

  1. jQuery在无冲突模式下加载。
  2. 插件代码运行,扩展上面的jQuery实例
  3. 我可以在我的应用程序中使用$,通过插件代码进行扩展,因此$ .myplugin可用。
  4. 我已经看到类似的问题浮出水面,但没有一个实际上解决了这个问题只给出了模糊的建议,比如“使用shim config”...

    修改

    我也尝试过使用

    jquery

    虽然插件方法在以这种方式加载为AMD模块后可用,但我仍然无法访问:"jquery-myplugin": { deps: ["jquery"], exports: "jQuery.fn.myplugin" } 因为默认的$ object尚未使用myplugin代码进行扩展。

3 个答案:

答案 0 :(得分:3)

使用jQuery.noConflict(true)删除jQuery全局变量。当您的插件加载时,它会尝试访问jQuery,但不能,导致此失败。

如果您的插件是一个模块,它可以访问jQuery作为依赖项。或者您可以将jQuery作为全局提供。

答案 1 :(得分:-1)

首先,确保" path / to / jquery-myplugin"实际上扩展了window.jQuery而不是$

noConflict()会保留window.jQuery个对象,但会从window.$取消绑定。在某些新浏览器window.$内置了本地document.querySelectorAll函数的别名。

其次,你的myplugin不需要返回自己,因为它本身不能使用。由于扩展 jQuery,从myplugin调用返回jQuery。

最后," path / to / jquery-myplugin"不是模块。它是一个普通的JS文件。它可能是RequireJS尝试像模块一样加载它而没有找到define()调用,这会导致混乱。尝试实际添加" .js"文件扩展名为引用信号给RequireJS,它需要使用" js!"插件加载资源。

require.config({
    paths: {
        "jquery": "path/to/jquery",
        "jquery-myplugin": "path/to/jquery-myplugin.js"
    },
    shim: {
        "jquery": {
          init: function() {
             return window.jQuery.noConflict();
          },
        "jquery-myplugin": {
          deps: ['jquery']
          init: function($) {
             return $;
          },
       }
    } 
});

答案 2 :(得分:-1)

我今天和你有同样的问题。以下是我可以解决的问题:

requirejs.config({
    "baseUrl": "js/lib",
    "paths": {
      "app": "../app"
    }
});

// Final version of jQuery with all needed plugins.
define("jquery", ["jquery-core", "myplugin"], function(jqCore) {
    return jqCore;
});

// Define core jQuery module.
define("jquery-core", ["jquery-1.9.1.min"], function() {
    return jQuery.noConflict(true);
});

// This module exposes jquery module to the global scope and returns previous defined version.
define("jq-global", ["jquery-core"], function(jqCore) {
    var tmp = jQuery;
    jQuery = jqCore;
    return tmp;
});

// Define your plugin here, and don't forget to reset previous jQuery version.
define("myplugin", ["jq-global", "jquery.myplugin"], function(jqGlobal, jqPlugin) {
    jQuery = jqGlobal;
});

// Load the main app module to start the app
requirejs(["app/main"]);

现在在我的app / main.js文件中,我可以执行以下操作:

define(["jquery"], function($) {
    $('body').myplugin();
});

这里的想法是在执行插件代码之前临时公开jQuery。到目前为止,我没有在更大的环境中测试解决方案,需要加载更多模块,所以我无法保证它能长期工作;)

修改

此解决方案无效!由于requirejs不会按顺序加载脚本,因此插件js文件可能会在jquery之前加载,这将导致执行失败。对不起。

如果有人有另一个想法......