Magento 2: Що таке тег `<кожен />`?


13

Наскільки я можу сказати, коли ви переглядаєте сітку в бекенде Magento, наступний шаблон "завантажений через XHR" KnockoutJS - це те, що починає візуалізацію речей

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>

Однак - я трохи втрачаю те, що таке <each/>тег і <render/>тег. Вони не є (або не здаються?) Частиною акцій KnockoutJS.

Я знаю, що можна додавати спеціальні теги до KnockoutJS за допомогою компонентів , але я не бачу очевидних місць, де компонент названий eachабо renderдоданий до KnockoutJS.

Отже, я не впевнений, чи це компоненти, зареєстровані десь, про які я не знаю, або якесь інше налаштування, яке Magento зробив для KnockoutJS, що дозволяє користувацькі теги, або щось інше цілком.

Примітка: я тут не повністю в темряві - я вважаю, що <each/>це, мабуть, перебирає кожний дочірній компонент ui, відображений у JSON, та рендерінг його шаблону (якщо такий шаблон існує).

Що мені зовсім не зрозуміло - це те, як ці теги реалізовані. Я хочу побачити, де вони реалізовані, щоб я міг налагоджувати, як пов'язані дані, а також зрозуміти механізм, який використовує Magento для створення цих тегів на випадок, якщо є інші.

Відповіді:


10

Як натякнув Рафаель , виявляється, що Magento завантажує свої шаблони KnockoutJS через запит XHR (тобто ajax), він також передає їх через деякі спеціальні процедури розбору, які шукають ряд спеціальних тегів та атрибутів

Цей спеціальний аналіз проводиться Magento_Ui/js/lib/knockout/template/rendererмодулем RequireJS. Вихідний код цього модуля встановлює кількість тегів та атрибутів за замовчуванням для пошуку. Існують також інші модулі, які можуть додавати до цього рендеру додаткові теги та атрибути. Наприклад, наступне

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

додасть <scope/>тег та scopeатрибут ( <div scope="...">) до списку атрибутів, що підлягають аналізу.

Є здається, основна ідея полягає в тому, щоб перевести ці теги і атрибути в рідні «tagless» шаблонні блоки Knockout. Наприклад, наступний шаблон Magento KnockoutJS

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

Переводиться на наступний нативний код KnockoutJS

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

Точні правила цього перекладу для мене ще незрозумілі - код у Magento_Ui/js/lib/knockout/template/rendererтрохи непрямий, і, схоже, вони можуть змінюватися від тега до тегу, атрибута до атрибута.

Я зібрав наступний фрагмент коду, який може завантажити шаблон Magento KnockoutJS і перекласти його в рідний код KnockoutJS.

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

Що стосується того, чому Magento може це зробити - я здогадуюсь, що хочеться виділити синтаксис і читати за шаблоном коментування KnockoutJS, але ніколи не виключайте більше причин, що стосуються Mallory-ish .


2

Обидва теги реалізовані під app/code/Magento/Ui/view/base/web/js/lib/knockout/template/renderer.js, я не надто впевнений, щоб зрозуміти, як саме вони реалізовані:

_.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);
    }
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.