Partager les ressources entre les différents modules amd
-
27-10-2019 - |
Question
Je développe actuellement une nouvelle application Web.
Ceci est la première fois que je utilise requirejs avec des modules AMD.
Il est pas facile de se habituer à ce nouveau paradigme qu'il ya - ce que je comprends -. Pas de variables dans l'espace de noms global
Dans les applications Web précédentes J'ai toujours eu une variable dans l'espace de noms global que je pourrais utiliser pour partager plusieurs ressources entre les différents modules.
Maintenant, avec requirejs AMD modules, j'utilise Backbone.js et jquery (les deux versions amd - jquery 1.7.1 et 0.5.3 Backbone.js-optamd3)
.Quelque part dans mon application, je vais chercher un module Backbone.js à partir du serveur (objet utilisateur). Je voudrais avoir accès à ce module de différents modules d'AMD. Je veux aussi avoir une application large objet d'événement.
Pouvez-vous me dire: quelle est la bonne façon requirejs AMD de partager des ressources à travers différents modules
?La solution
Je me suis trouvé une solution.
Merci, IntoTheVoid, pour votre réponse, mais j'espérais une solution AMD semblable. Cela signifie, pas encore, "polluer" l'espace de noms global.
Il y avait 2 clés de ma solution:
" https://github.com/addyosmani/backbone-aura " de Addy Osmani et « https://github.com/amdjs/amdjs-api/wiki/AMD » la spécification API le module asynchrone Définition (AMD).
La spécification dit: «Si l'usine est une fonction, il ne doit être exécutée une fois »
Donc, si un module amd est spécifié plusieurs fois en tant que dépendance dans une application Web, la dépendance est non seulement PAS CHARGÉ DES TEMPS DE PLUSIEURS , il est également NON EFFECTUÉ PLUSIEURS FOIS , ce qui est la chose nouvelle pour moi. Il est exécutée une seule fois et la valeur de retour de la fonction d'usine est maintenue. Chaque dépendance avec le même chemin d'accès a le même objet. Et cela change tout.
Alors, vous définissez simplement le module amd suivant:
define([], function() {
var app_registry = {};
app_registry.global_event_obj = _.extend({}, Backbone.Events);
app_registry.models = {};
return app_registry;
});
Maintenant, dans les modules où vous souhaitez partager des ressources, vous déclarez ce module app_registry comme la dépendance et à écrire dans un:
define(['jquery','underscore','backbone','app_registry'],
function ($, _, Backbone, app_registry){
var firstView = Backbone.View.extend({
initialize: function() {
_.bindAll (this, 'methodOne');
this.model.bind ('change', this.methodOne);
this.model.fetch();
},
methodOne: function() {
app_registry.models.abc = this.model;
}
...
et dans l'autre:
define(['jquery','underscore','backbone','app_registry'],
function ($, _, Backbone, app_registry){
var secondView = Backbone.View.extend({
initialize: function() {
_.bindAll (this, 'methodTwo');
app_registry.global_event_obj.bind ('special', this.methodTwo);
},
methodTwo: function() {
app_registry. ...
}
...
Autres conseils
Pour répondre à votre question de la façon de fournir une application large objet d'événement, vous pouvez créer un module amd appelé globalContext et instancier dans le main.js.
Par la suite, vous pouvez associer les paramètres à l'globalContext et utiliser le contexte mondial pour créer des sous-composants, etc.
//main.js file
require([ "./global-context" ], function( GlobalContext) {
new GlobalContext();
});
Dans le fichier global-context.js nous pouvons effectuer des tâches telles que les modules d'enfants de chargement
define(["Boiler", "./settings", "./modules/modules"],
function (Boiler, settings, modules) {
var GlobalContext = function () {
//here we use a template javascript class called Boiler.Context
var globalContext = new Boiler.Context("GlobalModule");
//add settings to the context which can be obtained globally throughout the application
globalContext.addSettings(settings);
//here we load the sub modules of the global context
globalContext.loadChildModules(modules);
};
Voici ce que nous avons mis en place dans BoilerplateJS , une architecture de référence pour javascript à grande échelle de développement de produits.
On peut utiliser le modèle initialize pour injecter une valeur quelconque dans un module de requirejs (aka "d'injection de dépendance).
Faites un appel besoin partout dans votre code:
var MyBackboneModule;
MyBackboneModule = someWayToGetAReferenceToIt();
require("module", function(Module) {
Module.initialize(MyBackboneModule);
});
Avec fichier défini comme module.js
define([], function(){
var BackboneModuleDoingThisAndThat;
function initialize(pBackboneModule) {
BackboneModuleDoingThisAndThat = pBackboneModule ;
};
function doSomething() {
var x = BackboneModuleDoingThisAndThat.computeThis(42);
};
return {
initialize: initialize
};
});
Vous pouvez définir un seul APP
global dans votre module d'AMD point d'entrée. APP
pourrait créer et maintenir une référence à d'autres modules partagés:
APP = {
this.settings : function() {
if(settingsModule == undefined){
//require, create and return it
} else {
return settingsModule;
}
}
}
Juste un commentaire sur votre réponse - vous n'avez pas besoin de définir une fonction dans votre module app_registry:
define({
global_event_obj: _.extend({}, Backbone.Events);
models: {}
});
suffire devrait le faire.
Voir: la documentation
Soyez prudent avec ces choses cependant. Il y a usecases où les modules de données partagées du sens. Mais si vous finissez par l'utiliser comme un pseudo espace de noms global, ce n'est pas beaucoup mieux que d'utiliser simplement globals (ne dis pas que ce que vous faites bien).