magento2中checkout_index_index.xml的“ displayArea”和“ provider”是什么意思


Answers:


22

要了解checkoutProviderdisplayArea是,你必须先了解你正在寻找的范围:jsLayout

jsLayout是结帐页面上JavaScript UI元素的一堆JavaScript配置。如果您查看module-checkout/view/frontend/templates/onepage.phtml,则会注意到以下x-magento-init-data:

<script type="text/x-magento-init">
    {
        "#checkout": {
            "Magento_Ui/js/core/app": <?php /* @escapeNotVerified */ echo $block->getJsLayout();?>
        }
    }
</script>

这就是一切的开始。它指出:

对于element #checkoutMagento_Ui/js/core/app使用以下信息初始化-component:...

它接收的信息是在布局XML中创建的信息:jsLayout。现在,这意味着您的XML 中的所有内容现在都传递给Magento_Ui/js/core/app-component(暂时不包括插件,布局处理器和其他东西……)

现在,我将不深入探讨如何module-ui/view/base/web/js/core/app.js精简一切,因为这会使这篇文章非常非常长,但是摘要如下:

  • Magento_Ui/js/core/app-component创建checkout-component。
  • 这将是该类型的组件uiComponent(这是一个非常通用的组件,可用于推迟使用您自己的自定义UI组件。它带有基本的剔除模板渲染和内容)。
  • 这将是我们的模板Magento_Checkout/web/frontend/template/onepage.html
  • 这将创建不同的儿童(名称errorsestimationsteps,等...)
  • steps孩子也将是uiComponent
  • 这个循环继续...配置使子项具有各种参数。

现在到你displayAreaprovider-question:正如你在上面看到的,一切都映射到的javascrip类。第一次看到使用displayArea是在创建类型为steps-component的时候uiComponent。因此uiComponent寻找的使用将是一个合乎逻辑的候选人displayArea

现在,a uiComponent是类型的JavaScript类Magento_Ui/js/lib/core/collection。(您可以在中查找此内容module-ui/view/base/requirejs-config.js)。这映射到module-ui/view/base/web/js/lib/core/collection.js。在这里,我们看到以下用法:

/**
 * Synchronizes multiple elements arrays with a core '_elems' container.
 * Performs elemets grouping by theirs 'displayArea' property.
 * @private
 *
 * @returns {Collection} Chainable.
 */
_updateCollection: function () {
    var _elems = compact(this._elems),
        grouped;

    grouped = _elems.filter(function (elem) {
        return elem.displayArea && _.isString(elem.displayArea);
    });
    grouped = _.groupBy(grouped, 'displayArea');

    _.each(grouped, this.updateRegion, this);

    this.elems(_elems);

    return this;
},

因此,这实际上是将uiComponent“映射”到特定的一组UI组件。要知道这一点很重要,因为它允许我们仅通过处理XML布局就可以将UI组件移动到布局中的其他位置,就像您使用phtml在服务器端呈现的模板一样。只需覆盖displayArea,您就可以在其他任何地方渲染任何JavaScript UI组件(假设目标区域也渲染在某个地方)。

现在,您的第二个问题是:provider。就像我们查找一样displayArea,我们应该首先开始查看UI组件Magento_Checkout/js/view/form/element/email。如果我们看一下requirejs-config.js,我们终于找到了module-checkout/view/frontend/web/js/view/form/element/email.js

但是... provider在此类中不使用。因此,让我们看看是否可以在它扩展的类中找到任何东西:(Component又是我们的uiComponent-class)。

但是...也不provider是。好吧,uiComponent只需扩展即可Element(位于module-ui/view/base/web/js/lib/core/element/element.js),所以让我们看一下:

/**
 * Parses 'modules' object and creates
 * async wrappers for specified components.
 *
 * @returns {Element} Chainable.
 */
initModules: function () {
    _.each(this.modules, function (name, property) {
        if (name) {
            this[property] = this.requestModule(name);
        }
    }, this);

    if (!_.isFunction(this.source)) {
        this.source = registry.get(this.provider);
    }

    return this;
},

答对了!事实证明,提供程序被用作从中获取数据的源。如果我们看一下的构造函数Element,您会默认看到它设置为空:

provider: '',

回到我们的配置。如果现在阅读我们的配置,我们将理解该项目shippingAddress是的组成部分Magento_Checkout/js/view/shipping,可以从中获取其数据checkoutProvider

这样就给我们留下了两个问题:

  1. 在哪里checkoutProvider定义?
  2. 它在运输JavaScript中如何使用?

好吧,如果您滚动到的底部checkout_index_index.xml,您会发现它只不过是一个香草uiComponent

<item name="checkoutProvider" xsi:type="array">
    <item name="component" xsi:type="string">uiComponent</item>
</item>

如果您看一下module-checkout/view/frontend/web/js/view/shipping.js,您会发现它的用法如下:

registry.async('checkoutProvider')(function (checkoutProvider) {
    var shippingAddressData = checkoutData.getShippingAddressFromData();

    if (shippingAddressData) {
        checkoutProvider.set(
            'shippingAddress',
            $.extend({}, checkoutProvider.get('shippingAddress'), shippingAddressData)
        );
    }
    checkoutProvider.on('shippingAddress', function (shippingAddressData) {
        checkoutData.setShippingAddressFromData(shippingAddressData);
    });
});

老实说:这是我分析的终点,因为这对我来说也变得很难搜索和投资正在发生的事情,但是我希望其他人可以从这里开始进行分析...

我知道这与registry.async()返回立即以回调函数作为参数执行的方法有关,但是其他人需要对此进行解释...


*免责声明:如果我错了,请务必纠正我!尚未真正尝试上述任何方法,但是我差不多已经使用Magento 2了一年了,我相信这是可行的。不幸的是,如果您想深入探究Magento海洋的底部,那么没有太多的文档资料。


2
那么displayArea是什么?
玛丽安齐克Šedaj

1
这是出色的分析,您是否进一步了解了?
LM_Fielding

11

我收到原始答案后的6个月,我认为我可以提供更好的答案displayArea

以我的理解,所有这些都与UI组件中的Knockouts的getTemplate()-方法,getRegion()-方法和子代一起使用。当您检查vendor/magento/module-checkout/view/frontend/templates/registration.phtml和时,可以看到一个很好的例子vendor/magento/module-checkout/view/frontend/web/template/registration.html

在中registration.phtml,您将看到具有子级的默认Magento UI组件:

<script type="text/x-magento-init">
    {
        "#registration": {
            "Magento_Ui/js/core/app": {
               "components": {
                    "registration": {
                        "component": "Magento_Checkout/js/view/registration",
                        "config": {
                            "registrationUrl": "<?php /* @escapeNotVerified */ echo $block->getCreateAccountUrl(); ?>",
                            "email": "<?php /* @escapeNotVerified */ echo $block->getEmailAddress(); ?>"
                        },
                        "children": {
                            "errors": {
                                "component": "Magento_Ui/js/view/messages",
                                "sortOrder": 0,
                                "displayArea": "messages",
                                "config": {
                                    "autoHideTimeOut": -1
                                 }
                            }
                        }
                    }
                }
            }
        }
    }
</script>

注意displayAreachildren-node中的使用。基本上,它告诉Knockout该子元素应该在称为“ messages”的区域中呈现。

现在看一下顶部registration.html

<!-- ko foreach: getRegion('messages') -->
    <!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->

这行Knockout代码的基本作用是:遍历displayArea'messages '中存在的所有子元素,并渲染它们。

基本上,如果您问我,命名会有些混乱。为什么要在一个地方使用“ displayArea”而在另一个地方使用region”。但是也许我的假设是完全错误的。也许Magento核心开发人员可以对此有所启发?


1
这么长的时间让我感到困惑,我不断看到getRegion,我的内心崩溃了。谢谢您的回答,非常有帮助!
本·克鲁克

1
好吧,这只是我的2美分。我希望某些核心开发人员可以就此主题分享一些看法。Magento 2的更深入的内部结构,尤其是整个Knockout / XHR实施,还没有得到很好的记录。
Giel Berkers '17

2
同意,除非您深入研究了许多核心文件,否则除了栈交换之外,别无其他方法可以了解到底发生了什么。
本·克鲁克
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.