Magento 2: कैसे / कहाँ `getTemplate` नॉकआउट समारोह बाध्य है?


19

कई Magento बैकएंड पृष्ठों में उनके स्रोत कोड में निम्नलिखित होते हैं

<!-- ko template: getTemplate() --><!-- /ko -->

मैं समझता हूं (या मुझे लगता है?) कि <!-- ko templateएक नॉकआउट जेएस कंटेनर-कम टेम्पलेट बाध्यकारी है

मेरे लिए क्या स्पष्ट नहीं है - getTemplate()समारोह को किस संदर्भ में कहा जाता है? मैंने जो उदाहरण ऑनलाइन देखे हैं, उनमें आमतौर पर एक जावास्क्रिप्ट ऑब्जेक्ट होता है template:। मैं मान रहा हूं कि getTemplateएक जावास्क्रिप्ट फ़ंक्शन है जो एक ऑब्जेक्ट लौटाता है - लेकिन कोई वैश्विक जावास्क्रिप्ट फ़ंक्शन नाम नहीं है getTemplate

कहां getTemplateबंधी है? या, संभवतः एक बेहतर सवाल, जहां मैगेंटो बैकएंड पेज पर नॉकआउट जेएस आवेदन बाध्यकारी होता है?

मुझे इसमें शुद्ध HTML / CSS / Javascript दृष्टिकोण से दिलचस्पी है। मुझे पता है कि Magento 2 में कई कॉन्फ़िगरेशन सार हैं (सिद्धांत में) डेवलपर्स को कार्यान्वयन विवरण के बारे में चिंता करने की आवश्यकता नहीं है। मुझे कार्यान्वयन विवरण में दिलचस्पी है।

जवाबों:


38

UI घटक के लिए PHP कोड इस तरह दिखने वाले एक जावास्क्रिप्ट आरंभण का प्रतिपादन करता है

<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app":{
                "types":{...},
                "components":{...},
            }
        }
    }
</script>       

पृष्ठ के इस बिट कोड का मतलब है कि Magento Magento_Ui/js/core/appकॉलबैक लाने के लिए आवश्यकता मॉड्यूल का आह्वान करेगा , और फिर कॉल करें कि {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मॉड्यूल मोड में होता है । आवेदन भी Magento_Ui/js/lib/ko/initializeआवश्यकताएँ पुस्तकालय लोड करता है। 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/...आवश्यकता है मॉड्यूल नॉकआउट के लिए एक एकल कस्टम बाइंडिंग सेट करता है ।

आवश्यकताएँ extender/...JJ मॉड्यूल देशी नॉकआउटJS वस्तुओं में कुछ सहायक तरीके जोड़ते हैं।

Magento भी ./template/engineआवश्यकता के मॉड्यूल में नॉकआउट के जावास्क्रिप्ट टेम्पलेट इंजन की कार्यक्षमता का विस्तार करता है ।

अंत में, मैगेंटो applyBindings()नॉकआउट जेएस ऑब्जेक्ट पर कॉल करता है। यह सामान्य रूप से है जहां एक नॉकआउट कार्यक्रम 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, तो नॉकआउट इस कस्टम scopeबाइंडिंग को ./bind/scopeदेखेगा , और आवश्यकताएँ मॉड्यूल को लागू करेगा । एक कस्टम बाइंडिंग लागू करने की क्षमता शुद्ध नॉकआउट जेएस है। कार्यान्वयन गुंजाइश बंधन के बारे में कुछ Magento इंक किया गया है।

स्कोप बाइंडिंग का कार्यान्वयन चालू है

#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:

तो, पहले से ही तत्काल घटक वस्तु क्या है ? 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कुंजी के लिए दिखेगा । यदि यह एक घटक कुंजी पाता है, तो यह होगा

  1. RequireJSमॉड्यूल उदाहरण वापस करने के लिए उपयोग करें - जैसे कि मॉड्यूल को एक requirejs/ defineनिर्भरता में कहा जाता था ।

  2. एक जावास्क्रिप्ट निर्माता के रूप में उस मॉड्यूल उदाहरण को कॉल करें

  3. परिणामी वस्तु को 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ऑब्जेक्ट है जो सेट है uiComponentuiComponentस्ट्रिंग एक RequireJS मॉड्यूल है। वास्तव में, इसकी एक आवश्यकता उर्फ ​​कि 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>

Magento इस ऑब्जेक्ट को रजिस्ट्री से वापस लाएगा, और इसे अंदर की चीजों के लिए व्यू मॉडल के रूप में बाँध देगा div। दूसरे शब्दों में, वह getTemplateविधि जिसे नॉकआउट ने टैगलेस बाइंडिंग ( <!-- ko template: getTemplate() --><!-- /ko -->) कहा जाता है, कहा जाता हैgetTemplatenew collection ऑब्जेक्ट पर विधि लागू ।


1
मुझे आपके उत्तर के प्रश्न 'क्यों' से नफरत है, इसलिए अधिक ध्यान केंद्रित प्रश्न यह होगा कि KO टेम्प्लेट्स को कॉल करने के लिए (प्रतीत होता है कि जटिल) प्रणाली का उपयोग करके M2 लाभ क्या है?
वृहस्पति

1
@ circlesix <uiComponents/>लेआउट XML सिस्टम से प्रतिपादन के लिए एक बड़ी प्रणाली का हिस्सा है। उन्हें मिलने वाले बेनिफ़िट्स में टैग के एक अलग सेट के लिए एक ही पृष्ठ पर दृश्य मॉडल स्वैप करने की क्षमता है।
एलन स्टॉर्म

16
मुझे नहीं पता कि हंसना है या रोना है! क्या झंझट है।
कोसो

8
मुझे लगता है कि वे अपनी कब्र खोद रहे हैं। अगर वे इस तरह की चीजों को
उलझाए रखते हैं

2
मैं लगभग 5 घंटे बिताने की कोशिश कर रहा हूं कि कैसे एक कस्टम व्यवहार को इस "जादू" द्वारा प्रदान किए गए एक फार्म व्यवहार को बांधने के लिए। समस्या का एक हिस्सा यह है कि इस अत्यधिक सामान्य ढांचे को आपको एक टन परतों के माध्यम से जाने की आवश्यकता है जब तक कि आपको चीजों को कैसे समझने का मौका है। इसके अलावा ट्रैकिंग जहां एक निश्चित विन्यास से आ रहा है अविश्वसनीय रूप से थकाऊ हो जाता है।
ग्रीनोन 83३

12

किसी भी पीएस टेम्पलेट के नॉकआउट के लिए बाइंडिंग मॉड्यूल की .xml फ़ाइलों में होती है। उदाहरण के रूप में चेकआउट मॉड्यूल का उपयोग करके आप contentटेम्पलेट के लिए कॉन्फ़िगरेशन पा सकते हैंvendor/magento/module-checkout/view/frontend/layout/default.xml

<block class="Magento\Checkout\Block\Cart\Sidebar" name="minicart" as="minicart" after="logo" template="cart/minicart.phtml">
    <arguments>
        <argument name="jsLayout" xsi:type="array">
            <item name="types" xsi:type="array"/>
                <item name="components" xsi:type="array">
                    <item name="minicart_content" xsi:type="array">
                        <item name="component" xsi:type="string">Magento_Checkout/js/view/minicart</item>
                            <item name="config" xsi:type="array">
                                <item name="template" xsi:type="string">Magento_Checkout/minicart/content</item>
                            </item>

इस फ़ाइल में आप देख सकते हैं कि ब्लॉक क्लास में नोड्स हैं जो "jsLayout" को परिभाषित करते हैं और कॉल आउट करते हैं <item name="minicart_content" xsi:type="array">। यह तर्क का एक छोटा सा रॉबिन है, लेकिन अगर आप में हैं तो आप vendor/magento/module-checkout/view/frontend/templates/cart/minicart.phtmlइस लाइन को देखेंगे:

<div id="minicart-content-wrapper" data-bind="scope: 'minicart_content'">
    <!-- ko template: getTemplate() --><!-- /ko -->
</div>

तो डेटा-बाइंड निर्देश देता है कि किसी भी नेस्टेड टेम्पलेट को कहाँ देखना है, इस मामले में यह तर्क Magento_Checkout/js/view/minicartके vendor/magento/module-checkout/view/frontend/web/js/view/minicart.jsलिए है (या मॉडल-व्यू-व्यू मॉडल सिस्टम में एमवी) और आपके पास Magento_Checkout/minicart/content(वी-नॉकआउट में मॉडल-व्यू-व्यू मॉडल है) प्रणाली) टेम्पलेट कॉल के लिए। तो इस स्पॉट में खींचा जाने वाला टेम्पलेट है vendor/magento/module-checkout/view/frontend/web/template/minicart/content.html

एक बार जब आप .xml की तलाश में उपयोग कर लेते हैं, तो यह पता लगाना मुश्किल नहीं है। इसमें से अधिकांश मैंने यहां सीखा है यदि आप टूटी-फूटी अंग्रेजी को अपना रास्ता बना सकते हैं। लेकिन अब तक मुझे लगता है कि नॉकआउट एकीकरण एम 2 का सबसे कम प्रलेखित हिस्सा है।


2
उपयोगी जानकारी, इसलिए +1, लेकिन सवाल के अनुसार, मुझे पता है कि मैगेंटो के पास इससे निपटने के लिए सार है - लेकिन मैं खुद को लागू करने के बारे में उत्सुक हूं। अर्थात - जब आप उस XML फ़ाइल में कुछ कॉन्फिगर करते हैं, तो magento यह सुनिश्चित करने के लिए कुछ और करता है कि आपका कॉन्फ़िगर किया हुआ मान तीसरी चीज़ करता है । मुझे किसी और चीज़ में और तीसरी चीज़ में दिलचस्पी है।
एलन स्टॉर्म

4

मुझे पूरा यकीन है कि आप जिस वैश्विक getTemplate जेएस विधि की तलाश कर रहे app/code/Magento/Ui/view/base/web/js/lib/core/element/element.jsहैं, वह आपके यहां परिभाषित है, आप इसे यहां पा सकते हैं: https://github.com/magento/magento2/blob/4d71bb4780625dce23274c90e457b7a72f345dd9/app/Magento/Ui/view/base/ /web/js/lib/core/element/element.js#L262

जैसा कि मैं अपने फोन पर हूँ मुझे यह पता लगाने में मुश्किल समय हो रहा है कि बाध्यकारी कैसे हो रहा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.