2011-02-02 12 views
62

Tengo un número de "clases" JavaScript cada una implementada en su propio archivo JavaScript. Para el desarrollo esos archivos se cargan individualmente, y para la producción están concatenados, pero en ambos casos tengo que definir manualmente una orden de carga, asegurándome de que B viene después de A si B usa A. Estoy planeando usar RequireJS como una implementación de CommonJS Modules/AsynchronousDefinition para resolver este problema automáticamente.RequireJS: ¿Cómo definir módulos que contienen una sola "clase"?

¿Hay una mejor manera de hacerlo que definir los módulos que exportan cada clase? Si no, ¿cómo nombras lo que exporta el módulo? Un módulo "empleado" que exporta una clase "Empleado", como en el ejemplo a continuación, no se siente lo suficiente como DRY.

define("employee", ["exports"], function(exports) { 
    exports.Employee = function(first, last) { 
     this.first = first; 
     this.last = last; 
    }; 
}); 

define("main", ["employee"], function (employee) { 
    var john = new employee.Employee("John", "Smith"); 
}); 

Respuesta

108

El AMD proposal le permite simplemente devuelve un valor para el objeto exportado. Pero tenga en cuenta que es una característica de la propuesta de AMD, es solo una propuesta de API, y hará que sea más difícil traducir el módulo a un módulo CommonJS regular. Creo que está bien, pero información útil para saber.

para que pueda hacer lo siguiente:

prefiero módulos que exportan una función constructora para comenzar con un nombre en mayúsculas, por lo que la versión no optimizada de este módulo también estaría en Employee.js

define("Employee", function() { 
    //You can name this function here, 
    //which can help in debuggers but 
    //has no impact on the module name. 
    return function Employee(first, last) { 
     this.first = first; 
     this.last = last; 
    }; 
}); 

Ahora en otro módulo, puede utilizar el módulo de empleado de esta manera:

define("main", ["Employee"], function (Employee) { 
    var john = new Employee("John", "Smith"); 
}); 
+0

Guau, una respuesta directa de @jrburke, mr. RequireJS mismo! +1! – Bart

98

como complemento a la respuesta de jrburke, tenga en cuenta que no tiene que devolver el c función del instructor directamente. Para las clases más útiles que también querrá agregar métodos a través del prototipo, que se puede hacer así:

define('Employee', function() { 
    // Start with the constructor 
    function Employee(firstName, lastName) { 
     this.firstName = firstName; 
     this.lastName = lastName; 
    } 

    // Now add methods 
    Employee.prototype.fullName = function() { 
     return this.firstName + ' ' + this.lastName; 
    }; 

    // etc. 

    // And now return the constructor function 
    return Employee; 
}); 

De hecho, este es exactamente el patrón mostrado en this example at requirejs.org.

+1

Hola Mark, tu publicación es exactamente lo que estoy buscando. Excepto una cosa. ¿Es posible definir algunos campos para el objeto Employee que no son parte del constructor? Por ejemplo, tiene la propiedad position y el método positionToUpper, pero de alguna manera define esa propiedad no en el constructor employee = new Employee ('john', 'smith'); employee.position = 'manager'; alerta (employee.positionToUpper()); –

+4

Alex, este ejemplo fue útil para mí, está muy bien documentado y probablemente pueda proporcionar los ejemplos que busca: https://gist.github.com/jonnyreeves/2474026 –

+0

@NathanPrather, que es una gran referencia; los comentarios ayudaron a traducir yo de un fondo de java – y3sh

Cuestiones relacionadas