Antworten:
Um zu verstehen , was checkoutProvider
und displayArea
sind, müssen Sie zunächst den Umfang verstehen , die Sie suchen in: jsLayout
.
jsLayout
ist eine Sammlung von JavaScript-Konfigurationen für die JavaScript-Benutzeroberflächenelemente auf der Checkout-Seite. Wenn Sie sich das ansehen module-checkout/view/frontend/templates/onepage.phtml
, werden Sie die folgenden x-magento-init
Daten bemerken:
<script type="text/x-magento-init">
{
"#checkout": {
"Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
}
}
</script>
Hier fängt alles an. Es sagt aus:
#checkout
Initialisieren Sie für element dieMagento_Ui/js/core/app
-Komponente mit den folgenden Informationen: ...
Und die Informationen , die sie erhält , ist die Information in dem Layout - XML erstellt: jsLayout
. Das bedeutet, dass jetzt alles in Ihrem XML- Magento_Ui/js/core/app
Code an die -Komponente übergeben wird (Plugins, Layoutprozessoren und ähnliches bleiben vorerst unberücksichtigt ...)
Ich werde jetzt nicht näher darauf eingehen, wie sich module-ui/view/base/web/js/core/app.js
alles zusammensetzt, denn das würde diesen Beitrag sehr, sehr lang machen, aber die Zusammenfassung lautet wie folgt:
Magento_Ui/js/core/app
-Komponente erzeugt eine checkout
-Komponente.uiComponent
(dies ist eine sehr generische Komponente, mit der Sie Ihre eigenen benutzerdefinierten UI-Komponenten von diesem Typ entfernen können. Sie enthält grundlegende Funktionen zum Rendern von Knockout-Vorlagen und ähnliches).Magento_Checkout/web/frontend/template/onepage.html
.errors
, estimation
, steps
, etc ...)steps
-Kind wird auch ein uiComponent
.Nun zu Ihrer displayArea
und provider
-Frage: Wie Sie oben gesehen haben, ist alles JavaScrip-Klassen zugeordnet. Das erste Mal sehen wir die Verwendung von, displayArea
wenn wir die steps
-Komponente erstellen , die vom Typ ist uiComponent
. Wäre uiComponent
also ein logischer Kandidat, nach der Verwendung zu suchen displayArea
.
Nun ist a uiComponent
eine JavaScript-Klasse des Typs Magento_Ui/js/lib/core/collection
. (Sie können dies in nachschlagen module-ui/view/base/requirejs-config.js
). Dies entspricht module-ui/view/base/web/js/lib/core/collection.js
. Hier sehen wir die folgende Verwendung:
/**
* 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;
},
Das bedeutet, dass eine uiComponent einer bestimmten Gruppe von UI-Komponenten zugeordnet wird. Dies ist wichtig zu wissen, da es uns ermöglicht, UI-Komponenten an andere Positionen im Layout zu verschieben, indem Sie einfach das XML-Layout bearbeiten, genau wie Sie dies mit phtml
Vorlagen tun würden , die serverseitig gerendert werden. Wenn Sie das überschreiben displayArea
, können Sie eine beliebige JavaScript-UI-Komponente an einer anderen Stelle rendern (vorausgesetzt, der Zielbereich wird auch irgendwo gerendert).
Nun zu Ihrer zweiten Frage: provider
. Genauso wie wir nachgesehen haben displayArea
, sollten wir uns zuerst die UI-Komponente ansehen Magento_Checkout/js/view/form/element/email
. Und wenn wir uns das anschauen requirejs-config.js
, finden wir endlich module-checkout/view/frontend/web/js/view/form/element/email.js
.
Aber ... nein provider
wird in dieser Klasse verwendet. Schauen wir also mal, ob wir irgendetwas in der Klasse finden können, die es erweitert: Component
(das ist wieder unsere uiComponent
Klasse).
Aber ... nein provider
auch. Naja, uiComponent
einfach ausdehnen Element
(was sich auf befindet module-ui/view/base/web/js/lib/core/element/element.js
), also lasst uns einfach dort hinüber schauen:
/**
* 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! Es stellt sich heraus, dass der Anbieter als Quelle zum Abrufen von Daten verwendet wird. Wenn wir uns den Konstruktor von ansehen Element
, werden Sie feststellen, dass er standardmäßig leer ist:
provider: '',
Also zurück zu unserer Konfiguration. Wenn wir jetzt unsere Konfiguration lesen, werden wir verstehen, dass das Element shippingAddress
eine Komponente von ist Magento_Checkout/js/view/shipping
, die seine Daten aus dem abruft checkoutProvider
.
Das lässt uns also zwei Fragen offen:
checkoutProvider
definiert?Wenn Sie nach unten scrollen checkout_index_index.xml
, werden Sie feststellen, dass es sich nur um eine Vanille handelt uiComponent
:
<item name="checkoutProvider" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
</item>
Und wenn Sie sich das ansehen module-checkout/view/frontend/web/js/view/shipping.js
, werden Sie feststellen, dass es so verwendet wird:
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);
});
});
Um ehrlich zu sein: Hier hört meine Analyse auf, weil es für mich auch schwierig wird zu suchen und zu investieren, was los ist, aber ich hoffe, jemand anderes kann es hier abholen ...
Ich weiß, es hat etwas mit der registry.async()
Rückgabe einer Methode zu tun, die sofort mit einer Rückruffunktion als Argument ausgeführt wird, aber jemand anderes muss dies erklären ...
* Haftungsausschluss: Bitte korrigieren Sie mich auf jeden Fall, wenn ich falsch liege! Ich habe noch keine der oben genannten Möglichkeiten ausprobiert, aber ich arbeite seit fast einem Jahr mit Magento 2 und glaube, dass dies so funktioniert. Leider gibt es nicht viel Dokumentation, wenn Sie auf den Grund des Magento-Ozeans tauchen möchten.
6 Monate nach meiner ursprünglichen Antwort denke ich, dass ich eine bessere Antwort auf das geben kann, was displayArea
ist.
Meines getTemplate()
Erachtens getRegion()
hängt dies alles mit der Knockout- Methode, der -Methode und den untergeordneten Elementen in den UI-Komponenten zusammen. Ein gutes Beispiel hierfür ist bei der Prüfung von vendor/magento/module-checkout/view/frontend/templates/registration.phtml
und zu sehen vendor/magento/module-checkout/view/frontend/web/template/registration.html
.
In sehen registration.phtml
Sie eine Standard-Magento-UI-Komponente mit untergeordneten Elementen:
<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>
Beachten Sie die Verwendung von displayArea
im children
-Node. Grundsätzlich wird Knockout mitgeteilt, dass dieses untergeordnete Element in einem Bereich mit dem Namen "messages" gerendert werden soll .
Schauen Sie sich jetzt oben an registration.html
:
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
Grundsätzlich bewirkt diese Zeile des Knockout-Codes Folgendes: Sie durchläuft alle untergeordneten Elemente, die in den displayArea -Nachrichten enthalten sind , und rendert sie.
Grundsätzlich ist die Benennung etwas verwirrend, wenn Sie mich fragen. Warum sollten Sie "displayArea" an einem Ort und "region" an einem anderen Ort verwenden ? Aber vielleicht ist meine Annahme völlig falsch. Vielleicht könnte ein Magento-Kernentwickler etwas mehr Licht ins Dunkel bringen?
getRegion
und mein Verstand implodiert einfach. Danke übrigens für beide Antworten, sehr hilfreich!