Ich möchte requireJS verwenden und verwende jQuery. Ich möchte die kombinierte Version von requireJS und jQuery nicht verwenden, da ich nicht die neueste jQuery-Version verwende. Was ist der beste Weg für mich, mit requireJS zu arbeiten?
Ich möchte requireJS verwenden und verwende jQuery. Ich möchte die kombinierte Version von requireJS und jQuery nicht verwenden, da ich nicht die neueste jQuery-Version verwende. Was ist der beste Weg für mich, mit requireJS zu arbeiten?
Antworten:
Das ist auch meine genaue Frage! Ich muss auch eine ältere jQuery verwenden, aber auch "traditionellere" Javascript-Bibliotheken. Was ist die beste Technik, um das zu tun? (Ich kann Ihre Frage bearbeiten, um sie breiter zu gestalten, wenn Sie nichts dagegen haben.) Folgendes habe ich gelernt.
Der RequireJS-Autor James Burke erläuterte die Vorteile der kombinierten RequireJS + jQuery-Datei . Sie bekommen zwei Dinge.
Ein Modul jquery
ist verfügbar und es ist das jQuery-Objekt. Das ist sicher:
// My module depends on jQuery but what if $ was overwritten?
define(["jquery"], function($) {
// $ is guaranteed to be jQuery now */
})
jQuery ist bereits vor jedem geladen require()
oder define()
Sachen. Allen Modulen wird garantiert, dass jQuery bereit ist. Sie brauchen nicht einmal das require/order.js
Plugin, da jQuery grundsätzlich hartcodiert war, um zuerst geladen zu werden.
Für mich ist # 2 nicht sehr hilfreich. Die meisten realen Anwendungen haben viele .js
Dateien, die in der richtigen Reihenfolge geladen werden müssen - traurig, aber wahr. Sobald Sie Sammy oder Underscore.js benötigen, hilft die kombinierte RequireJS + jQuery-Datei nicht mehr.
Meine Lösung besteht darin, einfache RequireJS-Wrapper zu schreiben, die meine traditionellen Skripte mit dem Plugin "order" laden.
Angenommen, meine App verfügt über diese Komponenten (abhängig).
In meinen Augen ist alles darüber .js
ein "traditionelles" Skript. Alles ohne .js
ist ein RequireJS-Plugin. Der Schlüssel ist: High-Level-Inhalte (greatapp, my_sammy) sind Module, und auf tieferen Ebenen wird auf herkömmliche .js
Dateien zurückgegriffen.
Alles beginnt mit einem Booter, der RequireJS sagt, wie er anfangen soll.
<html>
<head>
<script data-main="js/boot.js" src="js/require.js"></script>
</head>
</html>
In habe js/boot.js
ich nur die Konfiguration und wie man die Anwendung startet.
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(); }
);
In habe greatapp.js
ich ein normal aussehendes Modul.
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};
}
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;
}
);
Diese Frage ist jetzt mindestens zwei Jahre alt, aber ich habe festgestellt, dass dies immer noch ein Problem mit RequireJS 2.0 ist (require-jquery.js verwendet jQuery 1.8.0, aber die neueste Version ist 1.8.2).
Wenn Sie diese Frage sehen, beachten Sie, dass require-jquery.js jetzt nur require.js und jquery.js sind, die zusammengefügt wurden. Sie können einfach require-jquery.js bearbeiten und die jQuery-Teile durch eine neuere Version ersetzen .
Update (30. Mai 2013) : Nachdem RequireJS über Pfade und Shim verfügt, gibt es eine neue Möglichkeit, jQuery- und jQuery-Plugins zu importieren, und die alte Methode ist weder erforderlich noch empfohlen . Hier ist eine gekürzte Version der aktuellen Methode:
requirejs.config({
"paths": {
"jquery": "//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min"
}
});
define(["jquery"], function($) {
$(function() {
});
});
Weitere Informationen finden Sie unter http://requirejs.org/docs/jquery.html .
Ich habe festgestellt, dass der beste Ansatz darin besteht, jQuery außerhalb meines RequireJS-Builds zu halten.
Fügen Sie einfach jquery.min.js in Ihr HTML ein. Dann erstellen Sie eine jquery.js-Datei mit so etwas ...
define([], function() {
return window.$;
});
Ich fand JasonSmiths Antwort enorm hilfreich, wahrscheinlich mehr als die Dokumentation von RequireJS.
Es gibt jedoch eine Möglichkeit zur Optimierung, um zu vermeiden, dass separate AJAX-Anforderungen für (winzige) Module zum Definieren von Definitionen ("require_jquery" "require_sammy") vorliegen. Ich würde vermuten, dass r.js dies in der Optimierungsphase tun würde, aber Sie können dies im Voraus tun, um nicht mit Path, BaseURI-System zu kämpfen.
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
Schließlich 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
}
})
Diese Struktur (ersetzt lose (Duplikate?) Das Order Plugin von RequireJS, aber) ermöglicht es Ihnen, die Anzahl der Dateien, die Sie für AJAX benötigen, zu reduzieren und der Definition von abhängigen und abhängigen Bäumen mehr Kontrolle zu verleihen.
Es gibt auch einen großen Vorteil, jQuery separat zu laden (normalerweise 100.000). Sie können das Caching auf dem Server steuern oder jQuery im localStorage des Browsers zwischenspeichern. Schauen Sie sich das AMD-Cache-Projekt hier an: https://github.com/jensarps/AMD-cache. Ändern Sie dann die Definition (Anweisungen, die "Cache!" Einschließen:) und sie bleibt (für immer :) im Browser des Benutzers hängen.
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
}
)
Hinweis zu jQuery 1.7.x + Es hängt sich nicht mehr an das Fensterobjekt an, daher funktioniert das oben Gesagte NICHT mit der unveränderten jQuery 1.7.x + -Datei. Dort müssen Sie Ihre jquery **. Js anpassen, um dies vor dem Schließen von "}) (window);" einzuschließen:
;window.jQuery=window.$=jQuery
Wenn in der Konsole "jQuery undefined" -Fehler vorliegen, handelt es sich um ein Zeichen, das die von Ihnen verwendete jQuery-Version nicht an das Fenster anfügt.
Codelizenz: Public Domain.
Angaben: JavaScript oben riecht nach "Pseudocode", da es sich um eine Paraphrasierung (manuelles Beschneiden) von viel detaillierterem Produktionscode handelt. Es ist nicht garantiert, dass der oben dargestellte Code funktioniert, und er wurde NICHT getestet, um wie dargestellt zu funktionieren. Audit, teste es. Semikolons wurden absichtlich weggelassen, da sie gemäß JS-Spezifikation nicht erforderlich sind und Code ohne sie besser aussieht.
Zusätzlich zur Antwort von jhs finden Sie die neueren Anweisungen auf der Github-Seite require-jquery in der Datei README.md. Es behandelt sowohl den einfachsten Ansatz der Verwendung einer kombinierten Datei jquery / require.js als auch die Verwendung einer separaten Datei jquery.js.