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

Requirejs 使用noConflict模式下的jQuery在require.js中加载不兼容AMD的jQuery插件的正确方法?,requirejs,amd,Requirejs,Amd,假设我想将jquery与使用标准闭包定义的标准、非amd支持的jquery插件一起使用:(函数($)($.fn.myplugin={…})(jquery)

假设我想将jquery与使用标准闭包定义的标准、非amd支持的jquery插件一起使用:
(函数($)($.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插件

我曾尝试将
jquerymyplugin
设置为
jquery
deps
(以及其他方法),但我始终无法让它工作

似乎我对以下场景有问题:

  • jQuery以无冲突模式加载
  • 插件代码运行,扩展了上面jQuery的实例
  • 我可以在我的应用程序中使用$,并通过插件代码进行扩展,因此$.myplugin可用
  • 我看到过类似的问题,但没有一个真正解决了这个问题,只给出了模糊的建议,比如“使用垫片配置”

    编辑

    我也试过使用

    "jquery-myplugin": {
        deps: ["jquery"],
        exports: "jQuery.fn.myplugin"
    }
    

    虽然插件方法在以这种方式加载为AMD模块后可用,但我仍然无法访问:
    $('.class').myplugin()
    作为默认$object并没有使用myplugin代码进行扩展。

    使用
    jQuery.noConflict(true)
    删除
    jQuery
    全局变量。加载插件时,它尝试访问
    jQuery
    ,但无法访问,导致此故障

    如果您的插件是一个模块,那么它可以作为依赖项访问jQuery。或者您可以将
    jQuery
    作为全局变量保留。

    首先,确保“path/to/jQuery myplugin”实际上扩展了
    窗口。jQuery
    而不是
    $

    noConflict()离开
    窗口。jQuery
    对象已定义,但从
    窗口解除绑定。$
    在一些新浏览器上
    窗口。$
    是本机
    文档的内置别名。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 $;
              },
           }
        } 
    });
    

    今天我和你有同样的问题。下面是我如何修复它的:

    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不按顺序加载脚本,因此可能在jquery之前加载插件js文件,这将导致执行失败。对不起


    如果有人有其他想法…

    谢谢Sean,我知道这里会发生什么,我想做的是正确地使用require.js,其中没有一个模块应该创建全局变量,如果需要,所有其他模块都将jQuery作为依赖项加载。如果是这样,您将无法使用未转换的插件。如果您希望jQuery仅作为一个模块可用,那么您必须将插件转换为使用
    define()
    ,以便声明对jQuery的依赖关系。感谢Sean,我的印象是,shim config仍然允许您在不使用全局依赖关系的情况下处理未启用AMD的模块。为了让第三方代码与AMD/require一起工作,你不得不修改第三方代码。Shim可以让你把一个简单的脚本变成一个模块,但是它不能让你获得依赖性。如果您将jQuery作为一个全局查询,它会成功的。令人遗憾的是,第三方的东西不能与AMD合作。当jQuery采用它时,我有很高的期望。当主干网将其移除后,很明显我们不会很快看到大规模采用。这是错误的。noConflict的代码如下:
    javascript noConflict:function(deep){if(window.$==jQuery){window.$=}if(deep&&window.jQuery==jQuery){window.jQuery==jQuery;}返回jQuery;},
    当您传递“deep”参数时,它也会解除绑定window.jQuery,因此,您可以在同一页上运行多个版本。您对此仍有问题吗?模块依赖项应在数组中表示:
    define(['dep1','dep2'…'depn'],function(dep1,dep2,…depn){})如上所述,这是一个很好的捕获,但这只是我在stackoverflow上的错误输入,根本问题仍然存在