Magento 2, “mixins” olarak adlandırılan şeyler Nasıl Uygulanır?


16

Magento 2'nin RequireJS tabanlı nesne sistemleri, "mixins" adı verilen bir özellik içerir. Bir Magento 2 mixini, bir yazılım mühendisinin normalde bir mixin / özellik olarak düşüneceği şey değildir . Bunun yerine, bir Magento 2 karışımı, bir nesne / değer ana program tarafından kullanılmadan önce bir RequireJS modülü tarafından döndürülen nesneyi / değeri değiştirmenizi sağlar. Bunun gibi bir Magento 2 karışımı yapılandırabilirsiniz (requirjs-config.js dosyasıyla)

var config = {
    'config':{
        'mixins': {
            //the module to modify
            'Magento_Checkout/js/view/form/element/email': {
                //your module that will do the modification
                'Pulsestorm_RequireJsRewrite/hook':true
            }
        }
    }
};

Ardından, hook.js(veya yapılandırdığınız RequireJS modülüne sahip olmanız) gerekir,

define([], function(){
    console.log("Hello");
    return function(theObjectReturnedByTheModuleWeAreHookingInto){
        console.log(theObjectReturnedByTheModuleWeAreHookingInto);
        console.log("Called");
        return theObjectReturnedByTheModuleWeAreHookingInto;
    };
});

bir işlev döndürür. Magento, değiştirmek istediğiniz "modül" e referans vererek bu işlevi çağıracaktır. Örneğimizde bu, RequireJS modülü tarafından döndürülen nesne olacaktır Magento_Checkout/js/view/form/element/email. Bu aynı zamanda bir işlev, hatta bir ölçekleyici değeri olabilir (RequireJS modülünün döndürdüğüne bağlı olarak).

Bu sistem mixins, orijinal RequireJS modülü tarafından döndürülen nesne extendyöntemi destekliyorsa, mixin benzeri davranışlar oluşturmanıza izin verdiği için çağrılmış gibi görünür .

define([], function(){
    'use strict';
    console.log("Hello");

    var mixin = {
        ourExtraMethod = function(){
            //...
        }
    };

    return function(theObjectReturnedByTheModuleWeAreHookingInto){
        console.log(theObjectReturnedByTheModuleWeAreHookingInto);
        console.log("Called");


        return theObjectReturnedByTheModuleWeAreHookingInto.extend(mixin);
    };
});

Ancak, sistemin kendisi sadece modül nesnesi oluşturmaya bağlamanın bir yoludur.

Önsöz bitti - Magento'nun bu işlevselliği nasıl uyguladığını bilen var mı? RequireJS web sitesi bahsedilmiyor (Google, RequireJS'in eklenti sayfasını isteyebileceğinizi düşünmesine rağmen ).

requirejs-config.jsDosyaların dışında , Magento 2'nin sadece temel javascriptinden bahsediyormixins üç dosyada

$ find vendor/magento/ -name '*.js' | xargs ack mixins
vendor/magento/magento2-base/lib/web/mage/apply/main.js
73:                            if (obj.mixins) {
74:                                require(obj.mixins, function () {
79:                                    delete obj.mixins;

vendor/magento/magento2-base/lib/web/mage/apply/scripts.js
39:            if (_.has(obj, 'mixins')) {
41:                data[key].mixins = data[key].mixins || [];
42:                data[key].mixins = data[key].mixins.concat(obj.mixins);
43:                delete obj.mixins;

vendor/magento/magento2-base/lib/web/mage/requirejs/mixins.js
5:define('mixins', [
24:     * Adds 'mixins!' prefix to the specified string.
30:        return 'mixins!' + name;
76:     * Iterativly calls mixins passing to them
80:     * @param {...Function} mixins
84:        var mixins = Array.prototype.slice.call(arguments, 1);
86:        mixins.forEach(function (mixin) {
96:         * Loads specified module along with its' mixins.
102:                mixins   = this.getMixins(path),
103:                deps     = [name].concat(mixins);
111:         * Retrieves list of mixins associated with a specified module.
114:         * @returns {Array} An array of paths to mixins.
118:                mixins = config[path] || {};
120:            return Object.keys(mixins).filter(function (mixin) {
121:                return mixins[mixin] !== false;
126:         * Checks if specified module has associated with it mixins.
137:         * the 'mixins!' plugin prefix if it's necessary.
172:    'mixins'
173:], function (mixins) {
237:        deps = mixins.processNames(deps, context);
252:            queueItem[1] = mixins.processNames(lastDeps, context);

mixins.jsDosya eklentisi bir RequireJS olarak görünmektedir (dayalı !...? Yorumlardaki bahisler - bu doğru) ama% 100 net değil ne zaman main.jsyascripts.js Magento tarafından çağırılan veya özel nasıl mixinsyapılandırma onu yapar requirejs-config.jsdinleyici / kanca sistemi içine Yukarıda tarif edilen.

Bu sistemin nasıl uygulandığı / uygulandığı / yapılandırıldığı hakkında bir açıklama yapan var mı?

Yanıtlar:


18

Doğrudan sorularınıza gitmek istiyorum ve daha sonra karışımlarla gerçekten neler yapabileceğinizi açıklığa kavuşturmaya çalışacağım eklentisi . İlk önce ilk şeyler.

uygulama

Buradaki en önemli şey, herhangi bir RequireJS eklentisinin belirli dosyaların yüklenmesini tamamen üstlenebilmesidir. Bu, çözümlenmiş bir bağımlılık olarak geçirilmeden önce bir modülün dışa aktarma değerinin değiştirilmesine izin verir.

Magento özel mixins eklentisinin aslında bu kabataslak uygulamasına bir göz atın :

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

Son ve en zorlu bölüm dinamik olarak 'sampleMixinPlugin!' istenen modüllere aktarın. Bunu yapmak için , orijinal RequireJS yükleme yöntemiyle işlenmeden önce bağımlılıkların listesini keser defineve requireçağırır ve değiştiririz. Biraz zor ve lib/web/mage/requirejs/mixins.jsnasıl çalıştığını görmek istiyorsanız uygulamaya bakmanızı tavsiye ederim .

Hata ayıklama

Bu adımları tavsiye ederim:

Ve sonuncu ama aynı derecede önemli olarak, yalnızca öznitelikten geçirilen yapılandırmayı genişletebildikleri için veya modülleriyle requiresjs/mixins.jshiçbir ilgisi yoktur :main.jsscript.jsdata-mage-init

<div data-mage-init='{
    "path/to/module": {
        "foo": "bar",
        "mixins": ["path/to/configuration-modifier"]
    }
}'></div>

Demek istediğim, önceki iki dosya bir modülün döndürdüğü değerle uğraşmaz, bunun yerine bir örneğin yapılandırmasını önceden işler.

Kullanım örnekleri

Öncelikle, "mixins" (yanlış adlandırma konusunda haklısınız) olarak adlandırılan kaydı gerçekte bir modülün dışa aktarılan değerini istediğiniz şekilde değiştirmeye izin veren düz ayarlamak istiyorum. Bunun daha genel bir mekanizma olduğunu söyleyebilirim.

Bir modül tarafından dışa aktarılan işleve ekstra işlevsellik eklemek için hızlı bir örnek:

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

Bir modül tarafından döndürülen herhangi bir nesne / işlev için gerçek bir mixin uygulayabilirsiniz ve extend yönteme .

Bir yapıcı işlevini genişletme:

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

Umarım bu sorularınızı cevaplar.

Saygılarımızla.


Teşekkür ederim! Aradığım tek şey - sahip olduğum diğer tek soru - mixinsyapılandırma ne x-magento-initve data-mage-inityapılandırmalar ne yapıyor ? ie - yukarıdaki örnekte, path/to/configuration-modifieryapılandırma verilerini değiştirebilecek bir geri arama da döndürür mü? Veya başka bir şey?
Alan Storm

Evet, kesinlikle! Yapılandırma verilerini değiştirebileceğiniz bir geri arama döndürmesi gerekiyor.
Denis Rul

ön uç şeyler etrafında yolunuzu oldukça iyi biliyor gibi görünüyor - bu iki soru hakkında herhangi bir fikir? magento.stackexchange.com/questions/147899/… magento.stackexchange.com/questions/147880/…
Alan Storm

4

Tamamlamak için Denis RUL en cevabını .

Yani, bir Magento sayfasına bakarsanız, Magento'yu <script/>yükleyen üç etiket aşağıdadır.

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

Bu RequireJS'nin kendisi ( require.js), mixins.jseklentisi ve birleştirilmiş RequireJS yapılandırması (requirejs-config.js ).

mixins.jsDosya bir RequireJS eklentisi tanımlar. Bu eklenti, diğer RequireJS modülünün örneklemelerini dinleyen RequireJS modüllerini yüklemek ve çağırmaktan sorumludur.

Bu eklenti ayrıca mixin eklentisini tanımladıktan sonra bir requirjs programı içerir.

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

Bu ikinci program yükler sadece tanımlanmış mixinsbir bağımlılık olarak eklenti ve sonra yeniden tanımlayan küresel require, defineve requirejsişlevleri. Bu yeniden tanımlama, "gerçekten bir mixin" sisteminin, şeyleri normal işlevlere geri aktarmadan önce RequireJS modülünün ilk örneğine bağlanmasına izin veren şeydir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.