UI 구성 요소의 PHP 코드는 다음과 같은 자바 스크립트 초기화를 렌더링합니다.
<script type="text/x-magento-init">
{
"*": {
"Magento_Ui/js/core/app":{
"types":{...},
"components":{...},
}
}
}
</script>
이 페이지의이 코드는 Magento가 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
모듈은 Magento의 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는 또한 ./template/engine
RequireJS 모듈 에서 Knockout의 자바 스크립트 템플릿 엔진 기능을 확장합니다 .
마지막으로 Magento applyBindings()
는 KnockoutJS 객체를 호출 합니다. 일반적으로 Knockout 프로그램은 뷰 모델을 HTML 페이지에 바인딩하지만 Magento 는 뷰 모델 applyBindings
없이 호출합니다 . 즉, 녹아웃은 페이지를보기로 처리하기 시작하지만 데이터가 바인딩되지 않습니다.
스톡 녹아웃 설정에서는 약간 어리 석습니다. 그러나 앞에서 언급 한 사용자 정의 녹아웃 바인딩으로 인해 녹아웃이 작업을 수행 할 수있는 많은 기회가 있습니다.
범위 바인딩에 관심이 있습니다. 이 HTML에서 PHP UI 구성 요소 시스템으로 렌더링 된 것을 볼 수 있습니다.
<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'">
속성입니다. Magento가 시작 applyBindings
되면 Knockout은이 사용자 정의 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 객체를 생성 한 다음 div
사용 된 원본의 모든 하위 요소에 적용합니다 data-bind=scope:
.
그렇다면 이미 인스턴스화 된 구성 요소 객체는 무엇입니까? 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
종속성 에서 호출 된 것처럼 모듈 인스턴스를 반환하는 데 사용하십시오 .
해당 모듈 인스턴스 를 자바 스크립트 생성자로 호출
결과 객체를 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
.
text/x-magento-init
초기화 에서 JSON 객체를 보면
{
"*": {
"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
객체를, 그 구성 객체는이 component
에 설정되어 개체를 uiComponent
. uiComponent
문자열은 RequireJS 모듈입니다. 실제로 Magento_Ui/js/lib/core/collection
모듈에 해당하는 RequireJS 별명입니다 .
vendor/magento/module-ui/view/base/requirejs-config.js
14: uiComponent: 'Magento_Ui/js/lib/core/collection',
에서가 layout.js
, 마 젠토는 다음에 해당되는 코드를 실행하고있다.
//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>
Magento는이 객체를 레지스트리에서 다시 가져 와서 객체 내부의 뷰 모델로 바인딩합니다 div
. 즉, getTemplate
Knockout이 태그없는 바인딩 ( <!-- ko template: getTemplate() --><!-- /ko -->
)을 호출 할 때 호출 되는 getTemplate
메소드는 new collection
객체 의 메소드입니다 .