Bir UI bileşeninin PHP kodu şuna benzeyen bir javascript başlatması oluşturur
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/core/app":{
"types":{...},
"components":{...},
}
}
}
</script>
Sayfadaki bu kod biti, Magento'nun Magento_Ui/js/core/app
bir geri çağrı almak için RequireJS modülünü çağıracağı ve sonra {types:..., components:...}
JSON nesnesine argüman olarak geçen bu geri çağrıyı çağıracağı anlamına gelir ( data
aşağıda)
#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);
};
});
Veri nesnesi , UI bileşenini oluşturmak için gereken tüm verilerin yanı sıra belirli dizeleri belirli Magento RequireJS modüllerine bağlayan bir yapılandırma içerir. Bu eşleme types
ve layout
RequireJS modüllerinde gerçekleşir. Uygulama ayrıca Magento_Ui/js/lib/ko/initialize
RequireJS kitaplığını yükler . initialize
Magento'nın KnockoutJS entegrasyonu kapalı modül devreye giriyor.
/**
* 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();
});
Her bir bind/...
RequireJS modülü , Nakavt için tek bir özel ciltleme kurar .
extender/...
RequireJS modülleri yerli KnockoutJS nesnelere bazı yardımcı yöntemler ekleyin.
Magento, Knockout'un javascript şablon motorunun ./template/engine
RequireJS modülündeki işlevselliğini de genişletir .
Sonunda Magento applyBindings()
, KnockoutJS nesnesini çağırır . Bu genellikle bir Nakavt programının bir görünüm modelini HTML sayfasına bağlayacağı yerdir; ancak Magento, görünüm modeli applyBindings
olmadan çağrı yapar . Bu, Nakavt'ın bir görünüm olarak sayfayı işlemeye başlayacağı, ancak veri bağlı olmadığı anlamına gelir.
Bir nakavt kurulumunda, bu biraz aptalca olurdu. Bununla birlikte, daha önce bahsedilen özel Nakavt ciltleri nedeniyle, Nakavt'ın bir şeyler yapması için birçok fırsat var.
Kapsam bağlayıcılığıyla ilgileniyoruz . Bunu, PHP UI Bileşen sistemi tarafından da oluşturulan bu HTML'de görebilirsiniz.
<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>
Özellikle, data-bind="scope: 'customer_listing.customer_listing'">
öznitelik. Magento başladığında applyBindings
, Nakavt bu özel scope
bağlayıcıyı ./bind/scope
görür ve RequireJS modülünü çağırır . Özel bir bağlayıcı uygulama yeteneği saf KnockoutJS'dir. Uygulama bağlayıcı kapsamı şey Magento Inc. yapmış olduğunu.
Kapsam bağlayıcısının uygulanması
#File: vendor/magento/module-ui/view/base/web/js/lib/ko/bind/scope.js
Bu dosyadaki önemli kısım burada
var component = valueAccessor(),
apply = applyComponents.bind(this, el, bindingContext);
if (typeof component === 'string') {
registry.get(component, apply);
} else if (typeof component === 'function') {
component(apply);
}
Ayrıntılara fazla girilmeden, registry.get
yöntem, component
değişken içindeki dizeyi tanımlayıcı olarak kullanarak önceden oluşturulmuş bir nesneyi çıkarır applyComponents
ve üçüncü parametre olarak yönteme iletir. Dize tanımlayıcı değeri scope:
( customer_listing.customer_listing
yukarıda)
İçinde 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);
}
çağrısı createChildContext
, esasen, halihazırda başlatılmış bileşen nesnesine dayanan yeni bir viewModel nesnesinin ne olduğunu oluşturur ve bunu div
kullanılan orijinalin tüm alt öğelerine uygular data-bind=scope:
.
Peki, zaten somutlaştırılmış bileşen nesnesi nedir? layout
Geri çağrıyı hatırlıyor app.js
musunuz?
#File: vendor/magento/module-ui/view/base/web/js/core/app.js
layout(data.components);
layout
İşlev / modül içinde geçirilen içine inecek data.components
(yine, bu veriler ile geçirilen nesneden gelir text/x-magento-init
). Bulduğu her nesne için bir config
nesne arayacak ve bu yapılandırma nesnesinde bir component
anahtar arayacaktır . Bir bileşen anahtarı bulursa,
RequireJS
Bir modül örneğini döndürmek için kullanın - modül bir requirejs
/ define
bağımlılıkta çağrılmış gibi .
Bu modül örneğini javascript yapıcısı olarak adlandırın
Ortaya çıkan nesneyi registry
nesne / modülde saklayın
Bu, alınması gereken çok şey. İşte hızlı bir inceleme, kullanarak
<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>
başlangıç noktası olarak. scope
Değerdir customer_listing.customer_listing
.
text/x-magento-init
Başlatmadan JSON nesnesine bakarsak
{
"*": {
"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
Nesnenin bir config
nesnesi olduğunu ve bu yapılandırma nesnesinin olarak component
ayarlanmış bir nesnesi olduğunu görüyoruz uiComponent
. uiComponent
Dize RequireJS modülüdür. Aslında, Magento_Ui/js/lib/core/collection
modüle karşılık gelen bir RequireJS diğer adı .
vendor/magento/module-ui/view/base/requirejs-config.js
14: uiComponent: 'Magento_Ui/js/lib/core/collection',
İçinde layout.js
, Magento aşağıdakine eşdeğer bir çalışma kodu var.
//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*/})
}
Gerçekten merak uyandırmak için, toplama modeline bakarsanız ve yürütme yolunu izlerseniz collection
, bunun hem lib/core/element/element
modül hem de modül tarafından geliştirilmiş bir javascript nesnesi olduğunu keşfedeceksiniz lib/core/class
. Bu özelleştirmeleri araştırmak bu cevabın kapsamı dışındadır.
Bir kez başlatıldığında, layout.js
bunu object
kayıt defterinde saklar . Bu, Nakavt ciltleri işlemeye başladığında ve özel scope
ciltleme ile karşılaştığında
<div class="admin__data-grid-outer-wrap" data-bind="scope: 'customer_listing.customer_listing'">
<!-- snip -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!-- snip -->
</div>
Magento bu nesneyi kayıt defterinden geri getirecek ve içindeki şeyler için görünüm modeli olarak bağlayacaktır div
. Başka bir deyişle, getTemplate
Nakavt etiketsiz bağlayıcıyı ( <!-- ko template: getTemplate() --><!-- /ko -->
) çağırdığında çağrılan getTemplate
yöntem new collection
nesnedeki yöntemdir .