如何同时使用requireJS和jQuery?


82

我想使用requireJS和我正在使用jQuery。我不想使用requireJS和jQuery的组合版本,因为我没有使用最新的jQuery版本。我使用requireJS的最佳方法是什么?


2
是什么让您无法使用最新的jQuery?
隐身于2010年

我正在使用jQuery 1.3.8。此版本的工作方式与1.4.X有所不同。我要使用最新的jQuery,我必须更新一些代码,现在我没有时间这样做。而且,我认为合并软件包不是正确的事情。
瑙尔2010年

下面的答案很好...为什么您没有将其标记为正确?
囚犯零

@Prisoner ZERO:老实说,我还没有进行测试。最终,我使用了Microsoft的Ajax脚本加载器。感谢您提醒我标记此答案。如果您说很棒,我相信您。
瑙尔(Naor)

我还发现requirejs很难与其他库一起使用,反之亦然。这就是为什么我创建了一个易于使用且经过角度测试的库的原因。底部有一个演示应用程序:gngeorgiev.github.io/Modulerr.js您还可以将所有脚本合并为一个脚本,而无需依赖Modulerr.js
Georgi-it

Answers:


130

这也是我的确切问题!我还必须使用较旧的jQuery,但也必须使用更多的“传统” javascript库。最好的技术是什么?(如果您不介意,我可能会编辑您的问题以使其范围更广。)这是我所学到的。

RequireJS作者James Burke解释了组合RequireJS + jQuery文件优点。你得到两件事。

  1. 一个模块jquery可用,它是jQuery对象。这是安全的:

    // My module depends on jQuery but what if $ was overwritten?
    define(["jquery"], function($) {
      // $ is guaranteed to be jQuery now */
    })
    
  2. jQuery是之前任何已加载require()define()东西。所有模块均保证jQuery已准备就绪。您甚至不需要require/order.js插件,因为jQuery基本上是经过硬编码才能首先加载的。

对我来说,#2并不是很有帮助。大多数真实的应用程序都有许多 必须按正确顺序加载的.js文件-不好,但事实如此。一旦需要Sammy或Underscore.js,组合的RequireJS + jQuery文件就无济于事。

我的解决方案是编写简单的RequireJS包装器,以使用“ order”插件加载我的传统脚本。

假设我的应用程序具有这些组件(根据依赖性)。

  • 我的应用程式greatapp
    • greatapp取决于自定义jquery(我必须使用旧版本)
    • greatapp取决于my_sammy(SammyJS加上我必须使用的所有插件)。这些必须是有序的
      1. my_sammy取决于jquery(SammyJS是jQuery插件)
      2. my_sammy取决于sammy.js
      3. my_sammy取决于sammy.json.js
      4. my_sammy取决于sammy.storage.js
      5. my_sammy取决于sammy.mustache.js

在我看来,以上所有.js以“传统”脚本结尾的内容。没有的一切.js都是RequireJS插件。关键是:高级内容(greatapp,my_sammy)是模块,而在更深层次上,它可以回退到传统.js文件。

正在启动

一切都从引导程序告诉RequireJS如何开始开始。

<html>
  <head>
    <script data-main="js/boot.js" src="js/require.js"></script>
  </head>
</html>

js/boot.js我把仅有的配置,以及如何启动应用程序。

require( // The "paths" maps module names to actual places to fetch the file.
         // I made modules with simple names (jquery, sammy) that will do the hard work.
         { paths: { jquery: "require_jquery"
                  , sammy : "require_sammy"
                  }
         }

         // Next is the root module to run, which depends on everything else.
       , [ "greatapp" ]

         // Finally, start my app in whatever way it uses.
       , function(greatapp) { greatapp.start(); }
       );

主要用途

greatapp.js我有一个正常看模块。

define(["jquery", "sammy"], function($, Sammy) {
  // At this point, jQuery and SammyJS are loaded successfully.
  // By depending on "jquery", the "require_jquery.js" file will run; same for sammy.
  // Those require_* files also pass jQuery and Sammy to here, so no more globals!

  var start = function() {
    $(document).ready(function() {
      $("body").html("Hello world!");
    })
  }

  return {"start":start};
}

传统文件的RequireJS模块包装器

require_jquery.js

define(["/custom/path/to/my/jquery.js?1.4.2"], function() {
  // Raw jQuery does not return anything, so return it explicitly here.
  return jQuery;
})

require_sammy.js

// These must be in order, so use the "order!" plugin.
define([ "order!jquery"
       , "order!/path/to/custom/sammy/sammy-0.6.2-min.js"
       , "order!/path/to/custom/sammy/plugins/sammy.json-0.6.2-min.js"
       , "order!/path/to/custom/sammy/plugins/sammy.storage-0.6.2-min.js"
       , "order!/path/to/custom/sammy/plugins/sammy.mustache-0.6.2-min.js"
       ]

       , function($) {
           // Raw sammy does not return anything, so return it explicitly here.
           return $.sammy;
         }
      );

5
在此答案上做得很好...希望发问者将对此做标记!
囚犯零

您根据实际的jquery文件创建一个require_jquery模块,但是jquery不会保持全局性吗?从自定义路径加载的实际jquery文件1.4.2,不是require.js模块吗?还是您也需要包装该文件?
桑德

3
我想指出的是,在最新版本的jQuery(1.7)中,它已经支持模块,因此您所需要做的就是按常规要求它,并且它将起作用。
MikeMurko 2011年

1
有人可以更新此答案以反映出如何执行requireAMD 2(带垫片)+支持AMD的jQuery 1.7+吗?
亨利

1
我只想指出,现在,使用非AMD javascript文件实现依赖关系支持的最佳方法是RequireJS 2.0+中提供的垫片配置。如果您仍在使用Require 1.x,则可以使用垫片的前身,wrapjs
约翰

32

这个问题现在已经至少两年了,但是我注意到这仍然是RequireJS 2.0的问题(require-jquery.js使用jQuery 1.8.0,但是最新版本是1.8.2)。

如果您碰巧看到此问题,请注意,require-jquery.js现在只是require.js和jquery.js,混在一起了。 您可以只编辑require-jquery.js并将jQuery部分替换为较新的版本

更新(2013年5月30日):现在RequireJS具有路径和填充程序,有了导入jQuery和jQuery插件的新方法,不再需要也不推荐使用旧方法。这是当前方法的简化版本:

requirejs.config({
    "paths": {
      "jquery": "//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min"
    }
});

define(["jquery"], function($) {
    $(function() {
    });
});

有关更多信息,请参见http://requirejs.org/docs/jquery.html


谢谢,这仍然很重要:)
Naor 2012年

您还在使用jQuery 1.3.8吗?:)
克里斯

感谢您指出这一点。我读到1.8的较旧版本存在最新解决的问题。
布莱恩·莫克洛

确实。它们不是curCSS的jQueryUI问题,不是吗?
克里斯(Chris

1
@AHMED:他们都工作。区别在于define明确指定了一个模块。我倾向于宁愿几乎只使用define,因为它对路径更明确:stackoverflow.com/questions/16087635/…–
克里斯

9

我发现最好的方法是将jQuery保留在我的RequireJS构建之外。

只需在您的HTML中包含jquery.min.js。然后,使用以下内容制作一个jquery.js文件...

define([], function() {
    return window.$;
});

这是一个不错的解决方法,因为我有一些JS文件,这些文件传统上必须使用脚本标签加载,并且它们依赖于jQuery。
jingtao 2014年

3

发现JasonSmith的答案非常有帮助,可能比RequireJS的文档还要有用。

但是,有一种方法可以对其进行优化,以避免对(微小的)定义声明模块(“ require_jquery”“ require_sammy”)有单独的AJAX请求。我怀疑r.js会在优化阶段做到这一点,但是您可以提前做到这一点,以免与BaseURI系统Path产生冲突。

index.html:

<html>
  <head>
    <script data-main="js/loader.js" src="js/require.js"></script>
  </head>
</html>

loader.js:

// We are going to define( dependencies by hand, inline.
// There is one problem with that through (inferred from testing):
// Dependencies are starting to load (and execute) at the point of declaring the inline
// define, not at the point of require(
// So you may want to nest the inline-defines inside require( 
// this is, in a way, short replacement for Order plug in, but allows you to use
// hand-rolled defines, which the Order plug in, apparently does not allow.

var jQueryAndShims = ['jquery']

if(window.JSON == null){
    jQueryAndShims.push('json2')
    define(
        'json2'
        , ['js/libs/json2.min.js']
        , function() {
            return window.JSON
        }
    )
}
// will start loading the second we define it.
define(
    'jquery'
    , ['js/libs/jquery_custom.min.js']
    , function() {
        // we just pick up global jQuery here. 
        // If you want more than one version of jQuery in dom, read a more complicated solution discussed in
        // "Registering jQuery As An Async-compatible Module" chapter of
        // http://addyosmani.com/writing-modular-js/
        return window.jQuery 
    }
)

// all inline defines for resources that don't rely on other resources can go here.

// First level require(
// regardless of depends nesting in 'myapp' they will all start downloading 
// at the point of define( and exec whenever they want, 
// async in many browsers. Actually requiring it before the nested require makes
// sure jquery had *executed and added jQuery to window object* before
// all resolved depends (jquery plugins) start firing.
require(jQueryAndShims, function($) {

    // will start loading the second we define it.        
    define(
        'sammy_and_friends'
        , ['jquery','js/libs/jquery_pluginone.min.js','js/libs/jquery_plugintwo.min.js','js/libs/sammy.min.js']
        , function($) {
            // note, all plugins are unaltered, as they are shipped by developers.
            // in other words, they don't have define(.. inside.
            // since they augment global $ (window.jQuery) anyway, and 'jquery' define above picks it up
            // , we just keep on returning it.
            // Sammy is attached to $ as $.sammy, so returning just Sammy makes little sense
            return $
        }
    )

    // second level require - insures that Sammy (and other jQuery plugins) - 'sammy_and_friends' - is
    // loaded before we load Sammy plugins. I normally i would inline all sammy plugins i need 
    // (none, since i use none of them preferring jQuery's direct templating API
    // and no other Sammy plug in is really of value. )  right into sammy.js file. 
    // But if you want to keep them separate:
    require(['sammy_and_friends'], function() {

        // will start loading the second we define it.
        define(
            'sammy_extended'
            , ['sammy_and_friends','js/libs/sammy_pluginone.min.js','js/libs/sammy_plugintwo.min.js']
            , function($) {
                // as defined above, 'sammy_and_friends' actually returns (globall) jQuery obj to which
                // Sammy is attached.  So we continue to return $
                return $
            }
        )
        // will start loading the second we define it.
        define(
            'myapp'
            , ['sammy_extended', 'js/myapplication_v20111231.js'] 
            , function($, myapp_instantiator) {
                // note, myapplication may, but does not have to contain RequireJS-compatible define
                // that returns something. However, if it contains something like 
                // "$(document).ready(function() { ... " already it MAY fire before 
                // it's depends - 'sammy_extended' is fully loaded.
                // Insdead i recommend that myapplication.js returns a generator 
                // (app-object-generating function pointer)
                // that takes jQuery (with all loaded , applied plugins) 
                // The expectation is that before the below return is executed, 
                // all depends are loaded (in order of depends tree)
                // You would init your app here like so:
                return myapp_instantiator($)
                // then "Run" the instance in require( as shown below
            }
        )

        // Third level require - the one that actually starts our application and relies on
        // dependency pyramid stat starts with jQuery + Shims, followed by jQuery plugins, Sammy, 
        // followed by Sammy's plugins all coming in under 'sammy_extended'
        require(['jquery', 'myapp'], function($, myappinstance) {
            $(document).ready(function() {myappinstance.Run()})
        })
    }) // end of Second-level require
}) // end of First-level require

最后,myapplication.js:

// this define is a double-wrap.
// it returns application object instantiator that takes in jQuery (when it's available) and , then, that
// instance can be "ran" by pulling .Run() method on it.
define(function() {
    // this function does only two things:
    // 1. defines our application class 
    // 2. inits the class and returns it.
    return function($) {
        // 1. defining the class
        var MyAppClass = function($) {
            var me = this
            this._sammy_application = $.sammy(function() {
                this.raise_errors = true
                this.debug = true
                this.run_interval_every = 300
                this.template_engine = null
                this.element_selector = 'body'
                // ..
            })
            this._sammy_application.route(...) // define your routes ets...
            this.MyAppMethodA = function(blah){log(blah)}  // extend your app with methods if you want
            // ...
             // this one is the one we will .Run from require( in loader.js
            this.Run = function() {
                me._sammy_application.run('#/')
            }
        }
        // 2. returning class's instance
        return new MyAppClass($) // notice that this is INITED app, but not started (by .Run) 
        // .Run will be pulled by calling code when appropriate
    }
})

这种结构(松散地替换(重复?)RequireJS的Order插件,但是)使您可以修剪AJAX所需的文件数量,从而为depends和depends树的定义增加了更多控制。

单独加载jQuery(通常为100k)也有很大的好处-您可以控制服务器的缓存,也可以将jQuery缓存到浏览器的localStorage中。在https://github.com/jensarps/AMD-cache上查看AMD-Cache项目, 然后更改define(语句包括“ cache!”:它将(永远:))固定在用户的浏览器中。

define(
    'jquery'
    , ['cache!js/libs/jquery_old.min.js']
    , function() {
        // we just pick up global jQuery here. 
        // If you want more than one version of jQuery in dom, read a more complicated solution discussed in
        // "Registering jQuery As An Async-compatible Module" chapter of
        // http://addyosmani.com/writing-modular-js/
        return window.jQuery 
    }
)

关于jQuery 1.7.x +的注意事项不再将自身附加到窗口对象,因此以上内容不适用于未修改的jQuery 1.7.x +文件。在那里,您必须自定义jquery **。js,以在关闭“})(window);”之前包含此内容:

;window.jQuery=window.$=jQuery

如果控制台中出现“ jQuery undefined”错误,则表示您正在使用的jQuery版本未将自身附加到窗口。

代码许可:公共领域。

披露:JavaScript上面带有“伪代码”的味道,因为它是对更详细的生产代码的解释(手工修剪)。上述代码不能保证能正常工作,并且未经测试可以正常工作。审核,测试。分号是故意省略的,因为JS规范不需要分号,没有分号,代码看起来会更好。


与RequireJS战斗之后(事情乱七八糟,不遵守定义,需要嵌套。其他不可思议的行为)切换到Curl.JS并开始在晚上睡个好觉。它不是那么炒作,但是,该死,它是稳定且易于使用的!
ddotsenko 2012年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.