Magento 2: Was ist ein <each /> -Tag?


13

Soweit ich das beurteilen kann, wird beim Anzeigen eines Gitters im Magento-Backend die folgende KnockoutJS-Vorlage "Über XHR geladen" gerendert

File: vendor/magento//module-ui/view/base/web/templates/collection.html
URL:  http://magento.example.xom/pub/static/adminhtml/Magento/backend/en_US/Magento_Ui/templates/collection.html
<each args="data: elems, as: 'element'">
    <render if="hasTemplate()"/>
</each>

Allerdings - ich bin ein bisschen ratlos, was das <each/>Tag und das <render/>Tag sind. Sie sind nicht (oder scheinen nicht zu sein?) Ein Teil der Lager KnockoutJS.

Ich weiß, dass es möglich ist, über Komponenten benutzerdefinierte Tags zu KnockoutJS hinzuzufügen , aber ich sehe keine offensichtlichen Stellen, an denen eine Komponente KnockoutJS benannt eachoder renderhinzugefügt wird.

Daher bin ich mir nicht sicher, ob es sich um Komponenten handelt, die an einer mir nicht bekannten Stelle registriert sind, oder um eine andere Anpassung, die Magento an KnockoutJS vorgenommen hat und die benutzerdefinierte Tags ermöglicht, oder um etwas ganz anderes.

Hinweis: Ich bin hier nicht ganz im Dunkeln - ich verstehe, dass <each/>wahrscheinlich jede untergeordnete UI-Komponente, die in JSON gerendert wird, durchlaufen und deren Vorlage gerendert wird (sofern diese Vorlage vorhanden ist).

Was mir überhaupt nicht klar ist, wie diese Tags implementiert werden. Ich möchte sehen, wo sie implementiert sind, damit ich debuggen kann, wie Daten gebunden werden, und den Mechanismus verstehen, mit dem Magento diese Tags erstellt, falls es andere gibt.

Antworten:


10

Wie Raphael angedeutet hat, stellt sich heraus, dass Magento beim Herunterladen seiner KnockoutJS-Vorlagen über eine XHR- (dh Ajax-) Anforderung auch einige benutzerdefinierte Parsing-Routinen durchläuft, die nach einer Reihe von benutzerdefinierten Tags und Attributen suchen

Diese benutzerdefinierte Analyse wird vom Magento_Ui/js/lib/knockout/template/rendererRequireJS-Modul durchgeführt. Der Quellcode dieses Moduls richtet eine Reihe von Standardtags und -attributen ein, nach denen gesucht werden soll. Es gibt auch andere Module, die diesem Renderer zusätzliche Tags und Attribute hinzufügen können. Zum Beispiel das Folgende

#File: vendor/magento/module-ui/view/base/web/js/lib/knockout/bindings/scope.js
renderer
    .addNode('scope')
    .addAttribute('scope', {
        name: 'ko-scope'
    });

will fügt das <scope/>Tag und das scopeAttribut ( <div scope="...">) zur Liste der analysierbaren Attribute hinzu.

Ist scheint , wie die Grundidee diese Tags zu übersetzen ist und Attribute in native Knockout „tagless“ Schablonenblöcke. Zum Beispiel die folgende Magento KnockoutJS-Vorlage

<each args="data: elems, as: 'element'">
    <render if="hasTemplate()"/>
</each>

Übersetzt in den folgenden nativen KnockoutJS-Code

<!-- ko foreach: {data: elems, as: 'element'} -->
    <!-- ko if: hasTemplate() --><!-- ko template: getTemplate() --><!-- /ko --><!-- /ko -->
<!-- /ko -->

Die genauen Regeln dieser Übersetzung sind mir noch unklar - der Code in Magento_Ui/js/lib/knockout/template/rendererist ein wenig indirekt und es scheint, als könnten sie sich von Tag zu Tag, von Attribut zu Attribut ändern.

Ich habe das folgende Code-Snippet erstellt, mit dem eine Magento KnockoutJS-Vorlage heruntergeladen und in nativen KnockoutJS-Code übersetzt werden kann.

jQuery.get('http://magento-2-1-0.dev/static/adminhtml/Magento/backend/en_US/Magento_Ui/templates/collection.html', function(result){
    var renderer = requirejs('Magento_Ui/js/lib/knockout/template/renderer')
    var fragment = document.createDocumentFragment();
    $(fragment).append(result);

    //fragment is passed by reference, modified
    renderer.normalize(fragment);
    var string = new XMLSerializer().serializeToString(fragment);
    console.log(string);    
})

Was den Grund für Magento angeht, möchte ich, dass die Kommentarmaske von KnockoutJS Syntax hervorhebt und lesbar ist, schließt aber nie mehr mallory-artige Gründe aus .


2

Beide Tags sind unter implementiert app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js, ich bin mir jedoch nicht sicher, wie sie genau implementiert sind:

_.extend(preset.nodes, {
    foreach: {
        name: 'each'
    },

    /**
     * Custom 'render' node handler function.
     * Replaces node with knockout's 'ko template:' comment tag.
     *
     * @param {HTMLElement} node - Element to be processed.
     * @param {String} data - Data specified in 'args' attribute of a node.
     */
    render: function (node, data) {
        data = data || 'getTemplate()';
        data = renderer.wrapArgs(data);

        renderer.wrapNode(node, 'template', data);
        $(node).replaceWith(node.childNodes);
    }
});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.