รหัส PHP สำหรับองค์ประกอบ UI แสดงผลการเริ่มต้นจาวาสคริปต์ที่มีลักษณะเช่นนี้
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/core/app":{
"types":{...},
"components":{...},
}
}
}
</script>
โค้ดบิตนี้ในหน้าหมายความว่าวีโอไอพีจะเรียกใช้Magento_Ui/js/core/app
โมดูล RequireJS เพื่อดึงข้อมูลการโทรกลับแล้วเรียกว่าการติดต่อกลับนั้นผ่าน{types:..., components:...}
วัตถุ JSON เป็นอาร์กิวเมนต์ (data
ด้านล่าง)
#File: vendor/magento/module-ui/view/base/web/js/core/app.js
define([
'./renderer/types',
'./renderer/layout',
'Magento_Ui/js/lib/ko/initialize'
], function (types, layout) {
'use strict';
return function (data) {
types.set(data.types);
layout(data.components);
};
});
วัตถุข้อมูลมีข้อมูลทั้งหมดที่จำเป็นในการแสดงผลองค์ประกอบ UI เช่นเดียวกับการกำหนดค่าที่เชื่อมโยงสายบางอย่างกับโมดูล Magento RequireJS บางอย่าง การจับคู่นั้นเกิดขึ้นในโมดูลtypes
และlayout
RequireJS แอปพลิเคชันยังโหลดMagento_Ui/js/lib/ko/initialize
ไลบรารี RequireJS initialize
โมดูล kicks ปิดบูรณาการ KnockoutJS วีโอไอพี
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
/** Loads all available knockout bindings, sets custom template engine, initializes knockout on page */
#File: vendor/magento/module-ui/view/base/web/js/lib/ko/initialize.js
define([
'ko',
'./template/engine',
'knockoutjs/knockout-repeat',
'knockoutjs/knockout-fast-foreach',
'knockoutjs/knockout-es5',
'./bind/scope',
'./bind/staticChecked',
'./bind/datepicker',
'./bind/outer_click',
'./bind/keyboard',
'./bind/optgroup',
'./bind/fadeVisible',
'./bind/mage-init',
'./bind/after-render',
'./bind/i18n',
'./bind/collapsible',
'./bind/autoselect',
'./extender/observable_array',
'./extender/bound-nodes'
], function (ko, templateEngine) {
'use strict';
ko.setTemplateEngine(templateEngine);
ko.applyBindings();
});
แต่ละbind/...
โมดูล RequireJS แต่ละชุดตั้งค่าเดียวเชื่อมโยงที่กำหนดเองสำหรับการทำให้ลง
extender/...
โมดูล RequireJS เพิ่มวิธีการช่วยเหลือบางอย่างเพื่อวัตถุ KnockoutJS พื้นเมือง
Magento ยังขยายฟังก์ชันการทำงานของเอ็นจิ้น javascript แม่แบบของ Knockout ใน ./template/engine
เอ็นจิ้นโมดูล RequireJS
ในที่สุดวีโอไอพีก็เรียกapplyBindings()
หาวัตถุ KnockoutJS นี่เป็นเรื่องปกติที่โปรแกรม Knockout จะผูกโมเดลมุมมองเข้ากับหน้า HTML อย่างไรก็ตาม Magento จะเรียกapplyBindings
โดยไม่มีโมเดลมุมมอง ซึ่งหมายความว่าสิ่งที่น่าพิศวงจะเริ่มประมวลผลหน้าเว็บเป็นมุมมอง แต่ไม่มีการผูกข้อมูล
ในการตั้งค่าสิ่งที่น่าพิศวงหุ้นนี้จะโง่เล็กน้อย อย่างไรก็ตามเนื่องจากการผูกน็อกสิ่งที่น่าพิศวงตามที่กล่าวไว้ก่อนหน้านี้
เราสนใจขอบเขตการเชื่อมโยง คุณจะเห็นว่าใน HTML นี้แสดงผลโดยระบบ PHP UI Component
<div class="admin__data-grid-outer-wrap" data-bind="scope: 'customer_listing.customer_listing'">
<div data-role="spinner" data-component="customer_listing.customer_listing.customer_columns" class="admin__data-grid-loading-mask">
<div class="spinner">
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
</div>
</div>
<!-- ko template: getTemplate() --><!-- /ko -->
<script type="text/x-magento-init">
</script>
</div>
โดยเฉพาะdata-bind="scope: 'customer_listing.customer_listing'">
แอตทริบิวต์ เมื่อวีโอไอพีเริ่มต้นapplyBindings
ใหม่สิ่งที่น่าพิศวงจะเห็นการscope
ผูกแบบกำหนดเองนี้และเรียกใช้./bind/scope
โมดูล RequireJS ความสามารถในการใช้การผูกแบบกำหนดเองนั้นบริสุทธิ์ KnockoutJS การบังคับใช้ขอบเขตนั้นเป็นสิ่งที่ Magento Inc. ได้ทำไว้
การดำเนินการของขอบเขตการรวมอยู่ที่
#File: vendor/magento/module-ui/view/base/web/js/lib/ko/bind/scope.js
บิตสำคัญในไฟล์นี้อยู่ที่นี่
var component = valueAccessor(),
apply = applyComponents.bind(this, el, bindingContext);
if (typeof component === 'string') {
registry.get(component, apply);
} else if (typeof component === 'function') {
component(apply);
}
โดยไม่ได้รับรายละเอียดมากเกินไปregistry.get
วิธีการจะดึงวัตถุที่สร้างขึ้นแล้วโดยใช้สตริงในcomponent
ตัวแปรเป็นตัวระบุและส่งผ่านไปยังapplyComponents
วิธีการเป็นพารามิเตอร์ที่สาม ตัวระบุสตริงคือค่าของscope:
( customer_listing.customer_listing
ด้านบน)
ใน applyComponents
function applyComponents(el, bindingContext, component) {
component = bindingContext.createChildContext(component);
ko.utils.extend(component, {
$t: i18n
});
ko.utils.arrayForEach(el.childNodes, ko.cleanNode);
ko.applyBindingsToDescendants(component, el);
}
การเรียกร้องให้createChildContext
จะสร้างสิ่งที่เป็นหลักวัตถุ Viewmodel ใหม่บนพื้นฐานของวัตถุส่วนประกอบ instantiated แล้วและจากนั้นนำไปใช้กับทุกองค์ประกอบที่ลูกหลานของเดิมที่ใช้div
data-bind=scope:
ดังนั้นวัตถุองค์ประกอบinstantiated แล้วคืออะไร? จำสายที่จะlayout
กลับมาapp.js
?
#File: vendor/magento/module-ui/view/base/web/js/core/app.js
layout(data.components);
layout
ฟังก์ชั่น / โมดูลจะลงไปยังที่ผ่านdata.components
(อีกครั้งข้อมูลนี้มาจากวัตถุที่ส่งผ่านทางtext/x-magento-init
) สำหรับแต่ละวัตถุที่พบมันจะค้นหาconfig
วัตถุและในวัตถุการกำหนดค่านั้นจะค้นหาcomponent
คีย์ หากพบคีย์ส่วนประกอบมันจะ
ใช้RequireJS
เพื่อส่งคืนอินสแตนซ์โมดูล - ราวกับว่าโมดูลนั้นถูกเรียกใช้ในrequirejs
/ การdefine
พึ่งพา
เรียกอินสแตนซ์ของโมดูลนั้นเป็นตัวสร้าง javascript
เก็บวัตถุที่เป็นผลลัพธ์ในregistry
วัตถุ / โมดูล
ดังนั้นนี่เป็นเรื่องที่ควรพิจารณาก่อนการใช้งาน
<div class="admin__data-grid-outer-wrap" data-bind="scope: 'customer_listing.customer_listing'">
<div data-role="spinner" data-component="customer_listing.customer_listing.customer_columns" class="admin__data-grid-loading-mask">
<div class="spinner">
<span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span>
</div>
</div>
<!-- ko template: getTemplate() --><!-- /ko -->
<script type="text/x-magento-init">
</script>
</div>
เป็นจุดเริ่มต้น ค่า scope
customer_listing.customer_listing
ถ้าเราดูที่วัตถุ JSON จากการtext/x-magento-init
เริ่มต้น
{
"*": {
"Magento_Ui/js/core/app": {
/* snip */
"components": {
"customer_listing": {
"children": {
"customer_listing": {
"type": "customer_listing",
"name": "customer_listing",
"children": /* snip */
"config": {
"component": "uiComponent"
}
},
/* snip */
}
}
}
}
}
}
เราเห็นcomponents.customer_listing.customer_listing
วัตถุมีconfig
วัตถุและวัตถุ config ที่มีวัตถุที่ตั้งค่าให้component
สตริงเป็น RequireJS โมดูล ในความเป็นจริงมันเป็นนามแฝง RequireJS ที่สอดคล้องกับโมดูลuiComponent
uiComponent
Magento_Ui/js/lib/core/collection
vendor/magento/module-ui/view/base/requirejs-config.js
14: uiComponent: 'Magento_Ui/js/lib/core/collection',
ในlayout.js
Magento มีการเรียกใช้รหัสที่เทียบเท่าดังต่อไปนี้
//The actual code is a bit more complicated because it
//involves jQuery's promises. This is already a complicated
//enough explanation without heading down that path
require(['Magento_Ui/js/lib/core/collection'], function (collection) {
object = new collection({/*data from x-magento-init*/})
}
สำหรับสิ่งที่อยากรู้อยากเห็นอย่างแท้จริงหากคุณดูในรูปแบบของคอลเลกชันและปฏิบัติตามเส้นทางการดำเนินการคุณจะพบว่าcollection
เป็นวัตถุจาวาสคริปต์ที่ได้รับการปรับปรุงทั้งโดยlib/core/element/element
โมดูลและlib/core/class
โมดูล การค้นคว้าการปรับแต่งเหล่านี้อยู่นอกเหนือขอบเขตของคำตอบนี้
ทันทีที่อินสแตนซ์layout.js
เก็บobject
ไว้ในรีจิสทรี ซึ่งหมายความว่าเมื่อการทำให้ล้มลงเริ่มประมวลผลการรวมและพบการscope
ผูกแบบกำหนดเอง
<div class="admin__data-grid-outer-wrap" data-bind="scope: 'customer_listing.customer_listing'">
<!-- snip -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!-- snip -->
</div>
div
วีโอไอพีจะเรียกกลับวัตถุนี้ออกจากรีจิสทรีและผูกเป็นรูปแบบมุมมองสำหรับสิ่งที่อยู่ภายใน กล่าวอีกนัยหนึ่งgetTemplate
วิธีการที่เรียกว่าเมื่อการทำให้ล้มลงเรียกใช้การรวมแท็ก ( <!-- ko template: getTemplate() --><!-- /ko -->
) เป็นgetTemplate
วิธีบนnew collection
วัตถุ