Jawaban:
Untuk memahami apa checkoutProvider
dan displayArea
yang, Anda harus terlebih dahulu memahami ruang lingkup yang Anda cari di: jsLayout
.
jsLayout
adalah sekelompok konfigurasi JavaScript untuk elemen UI UI di halaman checkout. Jika Anda melihat module-checkout/view/frontend/templates/onepage.phtml
, Anda akan melihat data x-magento-init
-atau berikut :
<script type="text/x-magento-init">
{
"#checkout": {
"Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
}
}
</script>
Di sinilah semuanya dimulai. Ini menyatakan:
Untuk elemen
#checkout
, inisialisasiMagento_Ui/js/core/app
-komponen dengan informasi berikut: ...
Dan informasi yang diterimanya adalah informasi yang dibuat dalam tata letak XML: jsLayout
. Sekarang, ini berarti bahwa semua yang ada di XML Anda sekarang diteruskan ke Magento_Ui/js/core/app
-komponen (meninggalkan plugin, dan prosesor tata letak dan hal-hal lain dari persamaan untuk saat ini ...)
Sekarang, saya tidak akan membahas secara terperinci bagaimana module-ui/view/base/web/js/core/app.js
meruntuhkan segalanya, karena itu akan membuat posting ini sangat, sangat panjang, tetapi ringkasannya adalah ini:
Magento_Ui/js/core/app
-component menciptakan checkout
-komponen.uiComponent
(ini adalah komponen yang sangat umum yang dapat digunakan untuk menunda komponen UI kustom Anda sendiri. Muncul dengan rendering template knockout dasar dan lainnya).Magento_Checkout/web/frontend/template/onepage.html
.errors
, estimation
, steps
, dll ...)steps
anak juga akan menjadi uiComponent
.Sekarang untuk menuju ke displayArea
dan provider
-pertanyaan: Seperti yang Anda lihat di atas, semuanya memetakan ke kelas JavaScrip. Pertama kali kita melihat penggunaannya displayArea
adalah ketika kita membuat steps
-component, yang merupakan tipe uiComponent
. Jadi uiComponent
akan menjadi kandidat yang logis untuk mencari penggunaan displayArea
.
Sekarang, a uiComponent
adalah kelas tipe JavaScript Magento_Ui/js/lib/core/collection
. (Anda dapat melihat ini di module-ui/view/base/requirejs-config.js
). Ini memetakan ke module-ui/view/base/web/js/lib/core/collection.js
. Di sini kita melihat penggunaan berikut:
/**
* 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;
},
Jadi apa efeknya, ini 'memetakan' komponen lain ke grup komponen UI tertentu. Ini penting untuk diketahui, karena memungkinkan kita untuk memindahkan komponen UI ke lokasi lain dalam tata letak, dengan hanya memanipulasi tata letak XML, sama seperti Anda akan melakukan ini dengan phtml
templat yang diberikan sisi server. Cukup timpa displayArea
, dan Anda dapat membuat Komponen UI JavaScript apa pun di tempat lain (mengingat bahwa area target juga dirender di suatu tempat).
Sekarang untuk pertanyaan kedua: provider
. Sama seperti kita telah melihat ke atas displayArea
, kita harus mulai melihat Komponen UI terlebih dahulu, yaitu Magento_Checkout/js/view/form/element/email
. Dan jika kita melihat requirejs-config.js
, akhirnya kita temukan module-checkout/view/frontend/web/js/view/form/element/email.js
.
Tapi ... tidak provider
digunakan di kelas ini. Jadi mari kita lihat apakah kita dapat menemukan sesuatu di kelas yang diperluas: Component
(yang merupakan uiComponent
kelas kita lagi).
Tapi ... tidak provider
juga. Yah, uiComponent
cukup memanjang Element
(yang terletak di module-ui/view/base/web/js/lib/core/element/element.js
), jadi mari kita lihat di sana:
/**
* 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! Ternyata penyedia digunakan sebagai sumber untuk mengambil data dari. Jika kita melihat konstruktor Element
, Anda akan melihat bahwa secara default, itu diatur ke kosong:
provider: '',
Jadi kembali ke konfigurasi kita. Jika sekarang kita membaca konfigurasi kita, kita akan mengerti bahwa item tersebut shippingAddress
adalah komponen Magento_Checkout/js/view/shipping
, yang mengambil datanya dari checkoutProvider
.
Jadi itu meninggalkan kita dengan dua pertanyaan:
checkoutProvider
didefinisikan?Nah, jika Anda akan menggulir ke bagian bawah checkout_index_index.xml
, Anda akan melihat bahwa itu tidak lebih dari vanila uiComponent
:
<item name="checkoutProvider" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
</item>
Dan jika Anda melihat module-checkout/view/frontend/web/js/view/shipping.js
, Anda akan melihat bahwa itu digunakan seperti ini:
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);
});
});
Sejujurnya: di sinilah analisis saya berhenti, karena bagi saya juga sulit untuk mencari dan menginvestasikan apa yang terjadi, tetapi saya berharap orang lain dapat mengambilnya dari sini ...
Saya tahu itu ada hubungannya dengan registry.async()
mengembalikan metode yang akan segera dieksekusi dengan fungsi callback sebagai argumen, tetapi orang lain perlu menjelaskan ini ...
* Penafian: Dengan segala cara, mohon koreksi saya jika saya salah! Belum mencoba salah satu di atas secara nyata, tetapi saya telah bekerja hampir selama satu tahun sekarang dengan Magento 2 dan saya percaya ini adalah cara kerjanya. Sayangnya tidak ada banyak dokumentasi jika Anda ingin menyelam ke dasar Magento Ocean.
6 bulan setelah jawaban awal saya, saya pikir saya bisa memberikan jawaban yang lebih baik tentang apa displayArea
itu.
Dalam pemahaman saya, itu semua datang bersama-sama dengan getTemplate()
metode Knockouts , getRegion()
-method, dan anak-anak di Komponen UI. Contoh yang baik dari ini dapat dilihat saat Anda memeriksa vendor/magento/module-checkout/view/frontend/templates/registration.phtml
dan vendor/magento/module-checkout/view/frontend/web/template/registration.html
.
Di registration.phtml
, Anda akan melihat Komponen UI Magento default yang memiliki anak:
<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>
Perhatikan penggunaan displayArea
di children
-node. Pada dasarnya, ini memberi tahu Knockout bahwa elemen anak ini harus dirender di wilayah yang disebut 'pesan' .
Sekarang lihat bagian atas registration.html
:
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
Apa yang dilakukan oleh baris kode Knockout ini, adalah: ia memutari semua elemen anak yang ada di 'pesan' displayArea , dan menerjemahkannya.
Pada dasarnya, penamaannya agak membingungkan jika Anda bertanya kepada saya. Mengapa Anda menggunakan 'displayArea' di satu tempat, dan 'wilayah' di tempat lain. Tapi mungkin asumsi saya sama sekali tidak benar. Mungkin pengembang inti Magento bisa menyinari sedikit hal ini?
getRegion
dan pikiran saya meledak. Omong-omong, terima kasih atas kedua jawaban, sangat membantu!