Magento 2: cos'è un tag `<each />`?


13

Per quanto posso dire, quando si visualizza una griglia nel backend di Magento, il seguente modello KnockoutJS "caricato su XHR" è ciò che inizia a rendere le cose

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>

Tuttavia, sono un po 'perplesso su cosa siano il <each/>tag e il <render/>tag. Non sono (o non sembrano essere?) Una parte del magazzino KnockoutJS.

So che è possibile aggiungere tag personalizzati a KnockoutJS tramite i componenti , ma non vedo alcun luogo ovvio in cui un componente venga chiamato eacho renderaggiunto a KnockoutJS.

Quindi, non sono sicuro che si tratti di componenti registrati da qualche parte di cui non sono a conoscenza o di qualche altra personalizzazione che Magento ha apportato a KnockoutJS che abilita tag personalizzati o qualcos'altro.

Nota: non sono completamente al buio qui - ho capito che <each/>probabilmente sta iterando su ogni componente dell'interfaccia utente figlio renderizzato in JSON e sta visualizzando il suo modello (se quel modello esiste).

Ciò su cui non sono affatto chiaro è come sono implementati questi tag. Voglio vedere dove sono implementati in modo da poter eseguire il debug del modo in cui i dati sono associati e capire anche il meccanismo che Magento sta usando per creare questi tag nel caso ce ne siano altri.

Risposte:


10

Come ha suggerito Raphael , si scopre che quando Magento scarica i suoi modelli KnockoutJS tramite una richiesta XHR (cioè ajax), li passa anche attraverso alcune routine di analisi personalizzate che cercano una serie di tag e attributi personalizzati

Questa analisi personalizzata viene eseguita dal Magento_Ui/js/lib/knockout/template/renderermodulo RequireJS. Il codice sorgente di questo modulo imposta una serie di tag e attributi predefiniti da cercare. Esistono anche altri moduli che possono aggiungere tag e attributi aggiuntivi a questo renderer. Ad esempio, quanto segue

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

aggiungerà il <scope/>tag e l' scopeattributo ( <div scope="...">) all'elenco degli attributi analizzabili.

E ' sembra che l'idea di base è quello di tradurre questi tag e attributi in Knockout blocchi template native "tagless". Ad esempio, il seguente modello Magento KnockoutJS

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

Si traduce nel seguente codice KnockoutJS nativo

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

Le regole esatte di questa traduzione non sono ancora chiare per me: il codice Magento_Ui/js/lib/knockout/template/rendererè un po 'indiretto e sembra che possano cambiare da tag a tag, da attributo ad attributo.

Ho acquisito il seguente frammento di codice che può scaricare un modello Magento KnockoutJS e tradurlo in codice KnockoutJS nativo.

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);    
})

Per quanto riguarda il motivo per cui Magento potrebbe farlo: la mia ipotesi è che desideri una sorta di evidenziazione della sintassi e leggibilità per il modello di commento di KnockoutJS, ma non esclude mai più ragioni di Mallory .


2

Entrambi i tag sono implementati sotto app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js, non sono troppo sicuro di capire esattamente come sono implementati però:

_.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);
    }
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.