Solución:
Me gustaría ir directamente a sus preguntas y luego trataré de aclarar lo que realmente puede hacer con el mixins enchufar. Entonces, lo primero es lo primero.
Implementación
Lo principal aquí es la capacidad de cualquier complemento de RequireJS para hacerse cargo por completo del proceso de carga de ciertos archivos. Esto permite modificar el valor de exportación de un módulo antes de que se pase como una dependencia resuelta.
Eche un vistazo a esta implementación esquemática de lo que Magento personaliza mixins el complemento es en realidad es:
// RequireJS config object.
// Like this one: app/code/Magento/Theme/view/base/requirejs-config.js
{
//...
// Every RequireJS plugin is a module and every module can
// have it's configuration.
config: {
sampleMixinPlugin: {
'path/to/the/sampleModule': ['path/to/extension']
}
}
}
define('sampleMixinPlugin', [
'module'
] function (module) {
'use strict';
// Data that was defined in the previous step.
var mixinsMap = module.config();
return {
/**
* This method will be invoked to load a module in case it was requested
* with a 'sampleMixinPlugin!' substring in it's path,
* e.g 'sampleMixinPlugin!path/to/the/module'.
*/
load: function (name, req, onLoad) {
var mixinsForModule = [],
moduleUrl = req.toUrl(name),
toLoad;
// Get a list of mixins that need to be applied to the module.
if (name in mixinsMap) {
mixinsForModule = mixinsMap[name];
}
toLoad = [moduleUrl].concat(mixinsForModule);
// Load the original module along with mixins for it.
req(toLoad, function (moduleExport, ...mixinFunctions) {
// Apply mixins to the original value exported by the sampleModule.
var modifiedExport = mixinFunctions.reduce(function (result, mixinFn) {
return mixinFn(result);
}, moduleExport);
// Tell RequireJS that this is what was actually loaded.
onLoad(modifiedExport);
});
}
}
});
La última y más desafiante parte es anteponer dinámicamente el ‘sampleMixinPlugin!’ subcadena a los módulos solicitados. Para hacer esto interceptamos define
y require
invocaciones y modificar la lista de dependencias antes de que sean procesadas por el método de carga RequireJS original. Es un poco complicado y recomendaría mirar la implementación lib/web/mage/requirejs/mixins.js
si quieres como funciona.
Depuración
Recomendaría estos pasos:
- Asegúrese de que la configuración de ‘mixins!’ el plugin está realmente ahí.
- Compruebe que se esté modificando la ruta a un módulo. Es decir, se vuelve de
path/to/module
paramixins!path/to/module
.
Y el último pero no menos importante, requiresjs/mixins.js
no tiene nada que ver con el main.js
o script.js
módulos, ya que solo pueden extender la configuración que se pasa desde el data-mage-init
atributo:
<div data-mage-init="{
"path/to/module": {
"foo": "bar",
"mixins": ["path/to/configuration-modifier"]
}
}"></div>
Quiero decir que los dos archivos anteriores no se meten con el valor devuelto por un módulo, sino que preprocesan la configuración de una instancia.
Ejemplos de uso
Para empezar, me gustaría dejar las cosas claras en cuanto a que los llamados “mixins” (tiene razón sobre el nombre incorrecto) en realidad permiten modificar el valor exportado de un módulo de la forma que desee. Yo diría que este es un mecanismo mucho más genérico.
Aquí hay una muestra rápida de cómo agregar funcionalidad adicional a la función que está siendo exportada por un módulo:
// multiply.js
define(function () {
'use strict';
/**
* Multiplies two numeric values.
*/
function multiply(a, b) {
return a * b;
}
return multiply;
});
// extension.js
define(function () {
'use strict';
return function (multiply) {
// Function that allows to multiply an arbitrary number of values.
return function () {
var args = Array.from(arguments);
return args.reduce(function (result, value) {
return multiply(result, value);
}, 1);
};
};
});
// dependant.js
define(['multiply'], function (multiply) {
'use strict';
console.log(multiply(2, 3, 4)); // 24
});
Puede implementar un mixin real para cualquier objeto / función devuelto por un módulo y no necesita depender del extend
método en absoluto.
Extendiendo una función constructora:
// construnctor.js
define(function () {
'use strict';
function ClassA() {
this.property = 'foo';
}
ClassA.prototype.method = function () {
return this.property + 'bar';
}
return ClassA;
});
// mixin.js
define(function () {
'use strict';
return function (ClassA) {
var originalMethod = ClassA.prototype.method;
ClassA.prototype.method = function () {
return originalMethod.apply(this, arguments) + 'baz';
};
return ClassA;
}
});
Espero que esto responda a sus preguntas.
Saludos.
Para completar la respuesta de Denis Rul.
Entonces, si miras una página de Magento, aquí tienes las tres <script/>
etiquetas que cargan Magento.
<script type="text/javascript" src="http://magento.example.com/pub/static/frontend/Magento/luma/en_US/requirejs/require.js"></script>
<script type="text/javascript" src="http://magento.example.com/pub/static/frontend/Magento/luma/en_US/mage/requirejs/mixins.js"></script>
<script type="text/javascript" src="http://magento.example.com/pub/static/_requirejs/frontend/Magento/luma/en_US/requirejs-config.js"></script>
Este es RequireJS en sí (require.js
), los mixins.js
plugin y la configuración de RequireJS fusionada (requirejs-config.js
).
los mixins.js
archivo define un complemento RequireJS. Este complemento es responsable de cargar y llamar a los módulos RequireJS que escuchan la creación de instancias de otros módulos RequireJS.
Este complemento además contiene un programa requirejs después de que define el complemento mixin.
require([
'mixins'
], function (mixins) {
'use strict';
//...
/**
* Overrides global 'require' method adding to it dependencies modfication.
*/
window.require = function (deps, callback, errback, optional) {
//...
};
//...
window.define = function (name, deps, callback) {
//...
};
window.requirejs = window.require;
});
Este segundo programa carga el recién definido mixins
complemento como una dependencia, y luego redefine lo global require
, define
y requirejs
funciones. Esta redefinición es lo que permite que el sistema “no es realmente un mixin” se conecte a la instanciación inicial del módulo RequireJS antes de devolver las cosas a las funciones normales.