Jak używać requireJS i jQuery razem?

Chciałbym użyć requireJS i używam jQuery. Nie chcę używać połączonej wersji requireJS i jQuery, ponieważ nie używam najnowszej wersji jQuery. Jaki jest najlepszy sposób dla mnie do pracy z requireJS?

Author: MatthewMartin, 2010-12-27

5 answers

To też jest moje dokładne pytanie! Muszę również użyć starszych jQuery, ale także bardziej "tradycyjnych" bibliotek javascript. Jaka jest najlepsza technika, aby to zrobić? (Mogę edytować Twoje pytanie, aby było bardziej obszerne, jeśli nie masz nic przeciwko.) Oto czego się nauczyłem.

RequireJS autor, James Burke, wyjaśnił zalety połączonego pliku RequireJS + jQuery. Masz dwie rzeczy.

  1. Dostępny jest moduł jquery, który jest obiektem jQuery. To jest Bezpieczny:

    // My module depends on jQuery but what if $ was overwritten?
    define(["jquery"], function($) {
      // $ is guaranteed to be jQuery now */
    })
    
  2. JQuery jest już załadowany przed require() lub define() rzeczy. Wszystkie moduły mają gwarancję, że jQuery jest gotowy. Nie potrzebujesz nawet wtyczki require/order.js, ponieważ jQuery był w zasadzie zakodowany do załadowania jako pierwszy.

Dla mnie numer 2 nie jest zbyt pomocny. Większość rzeczywistych aplikacji ma wiele .js pliki, które muszą załadować się we właściwej kolejności-smutne, ale prawdziwe. Jak tylko będziesz potrzebował Sammy ' ego lub podkreślenia.js, połączony plik RequireJS+jQuery nie pomocy.

Moim rozwiązaniem jest napisanie prostych wrapperów RequireJS, które ładują moje tradycyjne skrypty za pomocą wtyczki "order".

Przykład

Załóżmy, że moja aplikacja ma te składniki (według zależności).

  • Moja aplikacja, świetna aplikacja
    • greatapp zależy od niestandardowego jquery (stara wersja, której muszę użyć)
    • greatapp zależy od my_sammy (SammyJS plus wszystkie jego wtyczki, których muszę użyć). Te muszą być w zamówienie
      1. my_sammy zależy od jquery (SammyJS jest wtyczką jQuery)
      2. my_sammy zależy od sammy ' ego.js
      3. my_sammy zależy od sammy ' ego.json.js
      4. my_sammy zależy od sammy ' ego.magazyn.js
      5. my_sammy zależy od sammy ' ego.wąsy.js

Według mnie wszystko powyżej, co kończy się .js jest" tradycyjnym " skryptem. Wszystko bez .js jest wymaganiem plugin. Najważniejsze jest to, że rzeczy wysokiego poziomu (greatapp, my_sammy) to moduły, a na głębszych poziomach wraca do tradycyjnych plików .js.

Booting

Wszystko zaczyna się od bootera mówiącego RequireJS, jak zacząć.

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

W js/boot.js umieściłem tylko config i jak uruchomić aplikację.

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(); }
       );

Główna Aplikacja

W greatapp.js mam normalnie wyglądający moduł.

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 moduł owijarki wokół tradycyjnych pliki

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;
         }
      );
 127
Author: JasonSmith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-29 06:58:29

To pytanie ma już co najmniej dwa lata, ale zauważyłem, że jest to problem nadal z RequireJS 2.0 (require-jquery.js używa jQuery 1.8.0, ale najnowsza wersja to 1.8.2).

Jeśli przypadkiem widzisz to pytanie, zauważ, że require-jquery.js jest teraz tylko wymagać.js i jquery.js, zmiażdżone razem. możesz po prostu edytować require-jquery.js i zastąp części jQuery nowszą wersją .

Aktualizacja (30 Maja 2013) : Teraz, że RequireJS ma ścieżki i shim, jest nowy sposób importowania wtyczek jQuery i jQuery, a stara metoda nie jest już potrzebna ani zalecana . Oto skrócona wersja bieżącej metody:

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

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

Zobacz http://requirejs.org/docs/jquery.html aby uzyskać więcej informacji.

 32
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-10 14:26:37

Odkryłem, że najlepszym rozwiązaniem jest utrzymanie jQuery poza kompilacją RequireJS.

Po prostu dołącz jquery./ min.js w Twoim HTML. Następnie zrób jquery.plik js z czymś takim...

define([], function() {
    return window.$;
});
 8
Author: tkdave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-28 09:16:43

Okazało się, że Anwer JasonSmith jest niezwykle pomocny, prawdopodobnie bardziej niż dokumentacja wymagająca.

Istnieje jednak sposób, aby zoptymalizować go, aby uniknąć oddzielnych żądań AJAX dla (maleńkich) modułów deklarujących definiowanie ("require_jquery" "require_sammy"). Podejrzewałbym, że R. js zrobiłby to na etapie optymalizacji, ale można to zrobić z wyprzedzeniem, aby nie walczyć z systemem Path, BaseURI.

Indeks.html:

<html>
  <head>
    <script data-main="js/loader.js" src="js/require.js"></script>
  </head>
</html>
Ładowarka.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

Wreszcie, / align = "left" / 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
    }
})

Ta struktura (luźno zastępuje (duplikuje?) RequireJS ' s Order plugin, ale) pozwala przyciąć liczbę plików potrzebnych do AJAX, dodając więcej kontroli do definicji depends i depend tree.

Istnieje również duży bonus do osobnego ładowania jQuery ( który zwykle ma 100k) - możesz kontrolować buforowanie na serwerze lub buforować jQuery do localStorage przeglądarki. Spójrz na projekt AMD-Cache tutaj https://github.com/jensarps/AMD-cache następnie zmień polecenie define (na "cache!": i będzie (na zawsze :) ) utknął w przeglądarce użytkownika.

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 
    }
)

Uwaga o jQuery 1.7.x+ nie przywiązuje się już do obiektu window, więc powyższe nie będzie działać z niezmodyfikowanym jQuery 1.7.plik x+. Tam musisz dostosować swoje jquery**.js to include this before the closing"}) (window);":

;window.jQuery=window.$=jQuery

Jeśli masz błędy "jQuery undefined" w konsoli, jest to znak jQuery wersja, której używasz, nie dołącza się do okna.

Licencja kodu: Public domain.

Ujawnienia: JavaScript powyżej pachnie "pseudo-kodem", ponieważ jest parafrazą (ręcznym przycinaniem) znacznie bardziej szczegółowego kodu produkcyjnego. Kod przedstawiony powyżej nie jest gwarantowany i nie został przetestowany do działania w sposób przedstawiony. Audyt, test. Średniki pominięte celowo, ponieważ nie są wymagane w specyfikacji JS, a kod wygląda lepiej bez nich.

 3
Author: ddotsenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-20 17:43:19

Oprócz odpowiedzi jhs, zobacz nowsze instrukcje na stronie require-jquery github z README.md plik. Obejmuje zarówno najprostsze podejście do używania połączonego jquery / require.pliku js, a także Jak używać osobnego jquery.js.

 1
Author: Paul Beusterien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-05 15:45:27