Відповіді:
Для того, щоб зрозуміти , що 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-компонент із такою інформацією: ...
А інформація , яку вона отримує це інформація , створена в макеті 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.
Тепер 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 у будь-якому іншому місці (враховуючи, що цільова область також десь надана).
Тепер для вашого другого запитання: 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.
Отже, ми залишаємо два питання:
checkoutProviderвизначено?Що ж, якщо ви прокрутите донизу 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, і я вважаю, що це працює. На жаль, не так багато документації, якщо ви хочете пірнути на дно океану Магенто.
Через 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 UI, який має дітей:
<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-ноді. В основному, це говорить нокауту, що цей дочірній елемент повинен бути відображений у регіоні, який називається "повідомлення" .
Тепер подивіться на верхню частину registration.html:
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
Що в основному робить цей рядок коду Knockout, це: він повторює всі дочірні елементи, які є у "повідомленнях" displayArea , і відображає їх.
В основному, називання трохи заплутане, якщо ви запитаєте мене. Чому б ви використовували "displayArea" в одному місці, а "region" в іншому. Але, можливо, моє припущення є абсолютно невірним. Можливо, розробник Magento core міг би просвітити на цьому трохи більше світла?
getRegionа мій розум просто розгортається. Дякую за обидві відповіді, до речі, дуже корисно!