¿Qué significa "displayArea" y "proveedor" de checkout_index_index.xml en magento2

Respuestas:

22

Para entender lo que checkoutProvidery displayAreason, primero hay que entender el alcance que busca en: jsLayout.

jsLayoutes un montón de configuración de JavaScript para los elementos de la interfaz de usuario de JavaScript en la página de pago. Si observa module-checkout/view/frontend/templates/onepage.phtml, notará los siguientes datos x-magento-init:

<script type="text/x-magento-init">
    {
        "#checkout": {
            "Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
        }
    }
</script>

Aquí es donde todo comienza. Afirma:

Para el elemento #checkout, inicialice el Magento_Ui/js/core/appcomponente con la siguiente información: ...

Y la información que recibe es la información creada en el XML de diseño: jsLayout. Ahora, esto significa que todo en su XML ahora se pasa al Magento_Ui/js/core/appcomponente (dejando complementos, procesadores de diseño y cosas fuera de la ecuación por el momento ...)

Ahora, no voy a profundizar en detalles sobre cómo se module-ui/view/base/web/js/core/app.jsreduce todo, porque eso haría que esta publicación sea muy, muy larga, pero el resumen es este:

  • El Magento_Ui/js/core/appcomponente crea un checkoutcomponente.
  • Este será un componente del tipo uiComponent(este es un componente muy genérico que se puede usar para diferir sus propios componentes personalizados de la interfaz de usuario. Viene con renderizado básico de plantilla y otras cosas).
  • Nos dará la plantilla Magento_Checkout/web/frontend/template/onepage.html.
  • Se va a crear varios niños (con el nombre errors, estimation, steps, etc ...)
  • El stepsniño también será un uiComponent.
  • Este ciclo continúa ... la configuración crea niños con varios parámetros.

Ahora bien, para llegar a su displayAreae provider-la pregunta: Como hemos visto más arriba, todo lo que se asigna a las clases JavaScrip. La primera vez que vemos el uso de displayAreaes cuando creamos el stepscomponente-, que es del tipo uiComponent. Por uiComponentlo tanto , sería un candidato lógico para buscar el uso de displayArea.

Ahora, a uiComponentes una clase de JavaScript del tipo Magento_Ui/js/lib/core/collection. (Puedes buscar esto en module-ui/view/base/requirejs-config.js). Esto se asigna a module-ui/view/base/web/js/lib/core/collection.js. Aquí vemos el siguiente uso:

/**
 * Synchronizes multiple elements arrays with a core '_elems' container.
 * Performs elemets grouping by theirs 'displayArea' property.
 * @private
 *
 * @returns {Collection} Chainable.
 */
_updateCollection: function () {
    var _elems = compact(this._elems),
        grouped;

    grouped = _elems.filter(function (elem) {
        return elem.displayArea && _.isString(elem.displayArea);
    });
    grouped = _.groupBy(grouped, 'displayArea');

    _.each(grouped, this.updateRegion, this);

    this.elems(_elems);

    return this;
},

Entonces, lo que esto hace es 'mapear' un uiComponent a un cierto grupo de componentes de la interfaz de usuario. Es importante saber esto, porque nos permite mover los componentes de la interfaz de usuario a otras ubicaciones en el diseño, simplemente manipulando el diseño XML, al igual que lo haría con phtmlplantillas que se representan en el lado del servidor. Simplemente anule el displayArea, y puede representar cualquier componente de la interfaz de usuario de JavaScript en cualquier otro lugar (dado que el área de destino también se representa en algún lugar).

Ahora la segunda pregunta: provider. Al igual que hemos buscado displayArea, deberíamos comenzar a mirar primero el componente de la interfaz de usuario, que es Magento_Checkout/js/view/form/element/email. Y si miramos el requirejs-config.js, finalmente encontramos module-checkout/view/frontend/web/js/view/form/element/email.js.

Pero ... no providerse usa en esta clase. Entonces, veamos si podemos encontrar algo en la clase que extiende: Component(que es nuestra uiComponentclase nuevamente).

Pero ... no providertambién. Bueno, uiComponentsimplemente se extiende Element(que se encuentra en module-ui/view/base/web/js/lib/core/element/element.js), así que echemos un vistazo allí:

/**
 * Parses 'modules' object and creates
 * async wrappers for specified components.
 *
 * @returns {Element} Chainable.
 */
initModules: function () {
    _.each(this.modules, function (name, property) {
        if (name) {
            this[property] = this.requestModule(name);
        }
    }, this);

    if (!_.isFunction(this.source)) {
        this.source = registry.get(this.provider);
    }

    return this;
},

¡Bingo! Resulta que el proveedor se utiliza como fuente para obtener datos. Si observamos el constructor de Element, verá que, de forma predeterminada, está configurado como vacío:

provider: '',

Así que volvamos a nuestra configuración. Si ahora leemos nuestra configuración, entenderemos que el elemento shippingAddresses un componente de Magento_Checkout/js/view/shipping, que obtiene sus datos del checkoutProvider.

Eso nos deja con dos preguntas:

  1. ¿Dónde se checkoutProviderdefine?
  2. ¿Cómo se usa en el envío JavaScript?

Bueno, si te desplazas hasta el fondo checkout_index_index.xml, notarás que no es más que una vainilla uiComponent:

<item name="checkoutProvider" xsi:type="array">
    <item name="component" xsi:type="string">uiComponent</item>
</item>

Y si observas module-checkout/view/frontend/web/js/view/shipping.js, verás que se usa así:

registry.async('checkoutProvider')(function (checkoutProvider) {
    var shippingAddressData = checkoutData.getShippingAddressFromData();

    if (shippingAddressData) {
        checkoutProvider.set(
            'shippingAddress',
            $.extend({}, checkoutProvider.get('shippingAddress'), shippingAddressData)
        );
    }
    checkoutProvider.on('shippingAddress', function (shippingAddressData) {
        checkoutData.setShippingAddressFromData(shippingAddressData);
    });
});

Para ser honesto: aquí es donde se detiene mi análisis, porque para mí también es difícil buscar e invertir lo que está sucediendo, pero espero que alguien más pueda retomarlo desde aquí ...

Sé que tiene algo que ver con la registry.async()devolución de un método que se ejecuta inmediatamente con una función de devolución de llamada como argumento, pero alguien más necesita explicar esto ...


* Descargo de responsabilidad: ¡Por supuesto, corrígeme si me equivoco! No he probado ninguno de los anteriores de verdad, pero llevo casi un año trabajando con Magento 2 y creo que así es como funciona. Desafortunadamente, no hay mucha documentación si quieres sumergirte en el fondo del Océano Magento.

Giel Berkers
fuente
2
Entonces, ¿qué es displayArea?
Marián Zeke Šedaj
1
Este es un análisis brillante, ¿alguna vez has desarrollado una comprensión más profunda?
LM_Fielding
11

6 meses después de mi respuesta original, creo que puedo proporcionar una mejor respuesta sobre lo que displayAreaes.

En mi opinión, todo se combina con el getTemplate()método Knockouts , el getRegion()método y los niños en los componentes de la interfaz de usuario. Un buen ejemplo de esto se puede ver cuando estás examinando vendor/magento/module-checkout/view/frontend/templates/registration.phtmly vendor/magento/module-checkout/view/frontend/web/template/registration.html.

En registration.phtml, verá un componente predeterminado de la interfaz de usuario de Magento que tiene elementos secundarios:

<script type="text/x-magento-init">
    {
        "#registration": {
            "Magento_Ui/js/core/app": {
               "components": {
                    "registration": {
                        "component": "Magento_Checkout/js/view/registration",
                        "config": {
                            "registrationUrl": "<?php /* @escapeNotVerified */ echo $block->getCreateAccountUrl(); ?>",
                            "email": "<?php /* @escapeNotVerified */ echo $block->getEmailAddress(); ?>"
                        },
                        "children": {
                            "errors": {
                                "component": "Magento_Ui/js/view/messages",
                                "sortOrder": 0,
                                "displayArea": "messages",
                                "config": {
                                    "autoHideTimeOut": -1
                                 }
                            }
                        }
                    }
                }
            }
        }
    }
</script>

Tenga en cuenta el uso de displayAreaen el childrennodo. Básicamente, le dice a Knockout que este elemento secundario debe representarse en una región llamada 'mensajes' .

Ahora eche un vistazo a la parte superior de registration.html:

<!-- ko foreach: getRegion('messages') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->

Lo que hace básicamente esta línea de código Knockout es: itera sobre todos los elementos secundarios que están presentes en los 'mensajes' de displayArea y los representa.

Básicamente, el nombre es un poco confuso si me preguntas. ¿Por qué usarías 'displayArea' en un lugar y 'region' en otro lugar? Pero tal vez mi suposición es totalmente incorrecta. ¿Quizás un desarrollador principal de Magento podría arrojar algo más de luz sobre esto?

Giel Berkers
fuente
1
Esto es lo que me ha confundido durante tanto tiempo, sigo viendo getRegiony mi mente simplemente explota. Gracias por las dos respuestas por cierto, ¡muy útil!
Ben Crook
1
Bueno, esto es solo mis 2 centavos. Espero que alguien de los desarrolladores principales pueda compartir algo de luz sobre este tema. Los aspectos internos más profundos de Magento 2, y especialmente la implementación completa de Knockout / XHR, son algo que no ha sido tan bien documentado.
Giel Berkers
2
De acuerdo, a menos que profundice en muchos de los archivos principales, no hay otra forma que este intercambio de pila para saber qué demonios está sucediendo.
Ben Crook