Magento 2:什么是`<each />`标签?


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 通过组件,但我没有看到任何明显的地方,一个组件命名eachrender添加到KnockoutJS。

因此,我不确定这些组件是否是我不知道的地方注册的组件,还是Magento对KnockoutJS进行的其他一些自定义,以启用自定义标签,或者完全是其他东西。

注意:我在这里并不完全是黑暗的-我得到<each/>的可能是遍历JSON中呈现的每个子ui组件,并呈现其模板(如果存在该模板)。

我完全不清楚这些标签是如何实现的。我想看看它们的实现位置,以便调试数据绑定方式,并了解Magento在创建其他标签时所使用的机制。

Answers:


10

正如Raphael所暗示的,事实证明,当Magento通过XHR(即ajax)请求下载其KnockoutJS模板时,它还会通过一些自定义解析例程传递它们,这些例程会查找许多自定义标签和属性。

此自定义解析由Magento_Ui/js/lib/knockout/template/rendererRequireJS模块完成。该模块的源代码设置了许多要搜索的默认标记和属性。还有其他模块可以向此渲染器添加其他标签和属性。例如,以下

#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="...">)添加到可分析属性的列表中。

好像基本思想是将这些标签转换和属性为本地敲除“无标签”模板块。例如,以下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的理由


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);
    }
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.