คำตอบ:
เพื่อให้เข้าใจถึงสิ่งที่checkoutProvider
และเป็นครั้งแรกที่คุณจะต้องเข้าใจถึงขอบเขตที่คุณกำลังมองหาใน:displayArea
jsLayout
jsLayout
คือการกำหนดค่า JavaScript จำนวนมากสำหรับองค์ประกอบ JavaScript UI บนหน้าเช็คเอาต์ หากคุณดูmodule-checkout/view/frontend/templates/onepage.phtml
คุณจะสังเกตเห็นx-magento-init
-data ต่อไปนี้:
<script type="text/x-magento-init">
{
"#checkout": {
"Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
}
}
</script>
นี่คือจุดเริ่มต้นของทุกสิ่ง มันระบุว่า:
สำหรับองค์ประกอบ
#checkout
เริ่มต้น - ส่วนMagento_Ui/js/core/app
ประกอบด้วยข้อมูลต่อไปนี้: ...
และข้อมูลที่ได้รับเป็นข้อมูลที่สร้างขึ้นในรูปแบบ jsLayout
XML: ตอนนี้หมายความว่าทุกอย่างใน XML ของคุณตอนนี้ถูกส่งผ่านไปยังMagento_Ui/js/core/app
-component (ปล่อยปลั๊กอินและตัวประมวลผลการจัดวางและสิ่งต่าง ๆ ออกจากสมการในขณะนี้ ... )
ตอนนี้ฉันจะไม่ลงลึกในรายละเอียดmodule-ui/view/base/web/js/core/app.js
ว่าจะทำให้ทุกอย่างเดือดลงได้อย่างไรเพราะนั่นจะทำให้โพสต์นี้ยาวมาก แต่บทสรุปก็คือ:
Magento_Ui/js/core/app
ส่วนประกอบสร้าง - checkout
ส่วนประกอบuiComponent
(นี่เป็นส่วนประกอบทั่วไปมากที่สามารถใช้เพื่อเลื่อนองค์ประกอบ UI ที่กำหนดเองของคุณเองมาพร้อมกับการแสดงผลเทมเพลตและสิ่งที่น่าพิศวงพื้นฐาน)Magento_Checkout/web/frontend/template/onepage.html
มันจะให้เราแม่แบบerrors
, estimation
, steps
ฯลฯ ... )steps
uiComponent
ตอนนี้เพื่อไปที่displayArea
และprovider
คำถามของคุณ: ตามที่คุณเห็นด้านบนทุกอย่างจะทำแผนที่กับคลาส JavaScrip ครั้งแรกที่เราเห็นการใช้displayArea
คือเมื่อเราสร้างsteps
-component 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;
},
ดังนั้นสิ่งนี้จะมีผลบังคับใช้คือ 'จับคู่ ui' กับคอมโพเนนต์ UI กลุ่มหนึ่ง สิ่งนี้เป็นสิ่งสำคัญที่ต้องทราบเนื่องจากช่วยให้เราสามารถย้ายส่วนประกอบ UI ไปยังตำแหน่งอื่น ๆ ในโครงร่างโดยเพียงแค่จัดการเลย์เอาต์ XML เช่นเดียวกับที่คุณทำกับphtml
เท็มเพลตที่แสดงผลฝั่งเซิร์ฟเวอร์ เพียงแค่แทนที่displayArea
และคุณสามารถแสดงผลคอมโพเนนต์ UI UI ได้ทุกที่อื่น (เนื่องจากพื้นที่เป้าหมายถูกแสดงผลที่ใดที่หนึ่ง)
ตอนนี้สำหรับคำถามที่สองของคุณ: provider
. เช่นเดียวกับที่เราเคยมองขึ้นdisplayArea
เราควรเริ่มมองหาที่ตัวแทน UI 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()
-method, the getRegion()
-method, และ children ใน UI Components เป็นตัวอย่างที่ดีของเรื่องนี้สามารถมองเห็นได้เมื่อคุณกำลังตรวจสอบและ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
-node โดยทั่วไปจะบอกสิ่งที่น่าพิศวงว่าองค์ประกอบเด็กคนนี้ควรจะแสดงผลในภูมิภาคที่เรียกว่า'ข้อความ'
ตอนนี้ดูที่ด้านบนของregistration.html
:
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
สิ่งที่เป็นบรรทัดของรหัสที่น่าพิศวงโดยทั่วไปคือ: มันวนซ้ำองค์ประกอบเด็กทั้งหมดที่มีอยู่ใน'ข้อความ' displayArea และทำให้พวกเขา
โดยพื้นฐานแล้วการตั้งชื่อค่อนข้างสับสนถ้าคุณถามฉัน ทำไมคุณถึงใช้'displayArea'ในที่เดียวและ'ภูมิภาค'ในที่อื่น แต่ข้อสันนิษฐานของฉันอาจไม่ถูกต้องทั้งหมด บางทีนักพัฒนาหลักของ Magento อาจส่องแสงเพิ่มเติมเล็กน้อย
getRegion
อยู่เรื่อย ๆ ขอบคุณสำหรับคำตอบทั้งสองทางมีประโยชน์มาก!