что означают «displayArea» и «поставщик» checkout_index_index.xml в magento2

Ответы:

22

Для того, чтобы понять , что checkoutProviderи displayAreaесть, вы должны сначала понять область , которую вы ищете в: jsLayout.

jsLayoutпредставляет собой набор настроек JavaScript для элементов пользовательского интерфейса JavaScript на странице оформления заказа. Если вы посмотрите на module-checkout/view/frontend/templates/onepage.phtml, вы увидите следующие x-magento-initданные:

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

Здесь все начинается. Здесь утверждается:

Для элемента #checkoutинициализируйте Magento_Ui/js/core/app-component следующей информацией: ...

А информация , которую она получает это информация , созданная в макете XML: jsLayout. Теперь это означает, что все в вашем XML теперь передается Magento_Ui/js/core/appкомпоненту (оставляя плагины, процессоры компоновки и прочее вне уравнения ...)

Теперь я не буду вдаваться в детали, как module-ui/view/base/web/js/core/app.jsвсе сводится к минимуму, потому что это сделало бы этот пост очень и очень длинным, но резюме таково:

  • Magento_Ui/js/core/appКомпонентный создает checkout-компонент.
  • Это будет компонент типа uiComponent(это очень общий компонент, который можно использовать для защиты ваших собственных компонентов пользовательского интерфейса. Он поставляется с базовыми шаблонами рендеринга и тому подобным).
  • Это будет нам шаблон Magento_Checkout/web/frontend/template/onepage.html.
  • Он будет создавать различные ребенок (с именем errors, estimation, stepsи т.д. ...)
  • steps-Child будет также uiComponent.
  • Этот цикл продолжается ... Конфигурация делает детей с различными параметрами.

Теперь , чтобы добраться до displayAreaи provider-question: Как вы уже видели выше, все карты на классы JavaScrip. Первый раз, когда мы видим использование, displayAreaэто когда мы создаем steps-компонент, который имеет тип uiComponent. Так uiComponentчто было бы логичным кандидатом для поиска использования displayArea.

Теперь a uiComponentявляется классом JavaScript этого типа Magento_Ui/js/lib/core/collection. (Вы можете посмотреть это в module-ui/view/base/requirejs-config.js). Это соответствует module-ui/view/base/web/js/lib/core/collection.js. Здесь мы видим следующее использование:

/**
 * 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;
},

Итак, что это делает в действительности, он «отображает» uiComponent на определенную группу компонентов пользовательского интерфейса. Это важно знать, потому что это позволяет нам перемещать компоненты пользовательского интерфейса в другие места в макете, просто манипулируя макетом XML, так же, как вы делали бы это с phtmlшаблонами, отображаемыми на стороне сервера. Просто переопределите displayArea, и вы можете отобразить любой компонент JavaScript UI где-либо еще (учитывая, что целевая область также отображается где-то).

Теперь для вашего второго вопроса: provider. Точно так же, как мы посмотрели вверх displayArea, мы должны начать смотреть на компонент пользовательского интерфейса, который есть Magento_Checkout/js/view/form/element/email. И если мы посмотрим на requirejs-config.js, мы, наконец, найдем module-checkout/view/frontend/web/js/view/form/element/email.js.

Но ... нет providerиспользуется в этом классе. Итак, давайте просто посмотрим, сможем ли мы найти что-нибудь в классе, который он расширяет: Component(который uiComponentснова является нашим -классом).

Но ... нет provider. Ну, uiComponentпросто расширяется Element(который находится в module-ui/view/base/web/js/lib/core/element/element.js), так что давайте просто посмотрим:

/**
 * 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;
},

Бинго! Оказывается, провайдер используется в качестве источника для получения данных. Если мы посмотрим на конструктор Element, вы увидите, что по умолчанию он пуст:

provider: '',

Итак, вернемся к нашей конфигурации. Если мы сейчас прочитаем нашу конфигурацию, мы поймем, что элемент shippingAddressявляется компонентом Magento_Checkout/js/view/shipping, который выбирает данные из checkoutProvider.

Так что у нас остается два вопроса:

  1. Где checkoutProviderопределяется?
  2. Как это используется в JavaScript доставки?

Ну, если вы прокрутите до конца checkout_index_index.xml, вы заметите, что это не что иное, как ваниль uiComponent:

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

И если вы посмотрите module-checkout/view/frontend/web/js/view/shipping.js, вы увидите, что он используется так:

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

Если честно: мой анализ останавливается, потому что мне также становится трудно искать и вкладывать деньги в то, что происходит, но я надеюсь, что кто-то другой сможет забрать это отсюда ...

Я знаю, что это как-то связано с registry.async()возвратом метода, который немедленно запускается с функцией обратного вызова в качестве аргумента, но кто-то еще должен объяснить это ...


* Отказ от ответственности: Пожалуйста, исправьте меня, если я ошибаюсь! Я не пробовал ничего из вышеперечисленного по-настоящему, но я почти год работаю с Magento 2, и я верю, что так оно и есть. К сожалению, нет большого количества документации, если вы хотите погрузиться на дно океана Magento.

Гиль Беркерс
источник
2
так что такое displayArea?
Мариан Зеке Шедай
1
Это блестящий анализ, вы когда-нибудь развивали понимание?
LM_Fielding
11

Через 6 месяцев после моего первоначального ответа, я думаю, что смогу дать лучший ответ о том, что displayAreaесть.

В моем понимании, все это идет вместе с Knockouts getTemplate()-методом, getRegion()-методом и потомками в компонентах пользовательского интерфейса. Хороший пример этого можно увидеть, когда вы изучаете vendor/magento/module-checkout/view/frontend/templates/registration.phtmlи vendor/magento/module-checkout/view/frontend/web/template/registration.html.

В registration.phtml, вы увидите компонент пользовательского интерфейса Magento по умолчанию, который имеет детей:

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

Обратите внимание на использование displayAreaв children-node. По сути, он сообщает Knockout, что этот дочерний элемент должен отображаться в области, называемой «messages» .

Теперь взгляните на верхнюю часть registration.html:

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

То, что в основном делает эта строка кода Knockout: она перебирает все дочерние элементы, присутствующие в «сообщениях» displayArea , и отображает их.

По сути, названия немного сбивают с толку, если вы спросите меня. Почему вы используете «displayArea» в одном месте и «регион» в другом месте. Но, возможно, мое предположение совершенно неверно. Возможно, разработчик ядра Magento мог бы пролить немного света на это?

Гиль Беркерс
источник
1
Это то, что смущало меня так долго, я продолжаю видеть, getRegionи мой ум просто взрывается. Кстати, спасибо за оба ответа, очень полезно!
Бен Крук
1
Ну, это только мои 2 цента. Я надеюсь, что кто-то из разработчиков ядра сможет немного осветить эту тему. Более глубокие внутренние аспекты Magento 2, и в особенности вся реализация Knockout / XHR, не очень хорошо документированы.
Giel Berkers
2
Согласитесь, если только вы не углубитесь во многие файлы ядра, у вас нет другого пути, кроме этого обмена стеками, чтобы узнать, что, черт возьми, происходит.
Бен Крук