您可能知道,Magento使用纯文本字段处理产品页面上的数量。这是一个保守的解决方案 - 它很简单,涵盖了所有的需求。但是,有时商家想要使用一些更吸引人的东西,其中许多人都会选择数量增量按钮(数量输入字段旁边的+和-按钮),这将是本文的主要内容。

处理这个问题或者任何其他相关的问题,很少有选项出现。我们可以使用老式的内联javascript来处理。因为我们使用的是Magento 2,所以我们也可以选择jQuery小部件的方式,并创建一个处理数量增量的小部件,我们在本文中将使用的是带有jQuery和Knockout.js的UI组件。

我们要做的第一件事是创建一个空模块,我们将它命名为magease_qtyincrementor。

它将位于/app/code/Magease/QtyIncrementors

为了让Magento能够看到我们的模块,我们需要创建etc/module.xmlregistration.php只需将常用内容放入其中(如果有错误,请检查核心模块)。
由于我们正在更改产品页面功能,因此我们必须找到显示默认数量字段的位置。

让我们做一些大胆的猜测:

  1. 它应该在核心文件中的某个地方
  2. 它应该在Catalog 模块中
  3. 它应该在前端模板中(view/frontend/templates 目录)
  4. 它是一个产品模板,因此它必须位于产品目录中
  5. 因为它不在产品列表中,所以它必须位于视图目录(产品/视图)中
  6. addtocart.phtml看起来很有趣,我们来看看吧

(我们现在有/app/code/Magento/Catalog/view/frontend/template/catalog/product/view/addtocart.phtml

并且,仔细检查后,它是:

<div class="control">
    <input type="number"
           name="qty"
           id="qty"
           maxlength="12"
           value="<?php /* @escapeNotVerified */ echo $block->getProductDefaultQty() * 1 ?>"
           title="<?php /* @escapeNotVerified */ echo __('Qty') ?>" class="input-text qty"
           data-validate="<?php echo $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>"
           />
</div>

正如预期的那样,它只是一个常规输入字段。
让我们改变它。将文件复制到您自己的模块:/app/code/Magease/QtyIncrementors/view/frontend/templates/catalog/product/view/addtocart.phtml

为了创建UI组件,我们需要初始化它。在输入字段下方的某处添加它。

<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "qty_change": {
                        "component": "Magease_QtyIncrementors/js/view/product/view/qty_change",
                        "defaultQty": <?php echo $block->getProductDefaultQty() * 1 ?>
                    }
                 }
            }
        }
    }
</script>

我们告诉Magento创建一个可以在所提到的路径中找到的组件(Magease_QtyIncrementors/js/view/product/view/qty_change- 转换为Magease/QtyIncrementors/view/frontend/web/js/view/product/view/qty_change.js),并且我们从服务器端传递了一个命名为'defaultQty'的参数

为了将此组件连接到前端的HTML,还需要做一件事。我们必须将它绑定到一些HTML元素。检查一下:

<div class="control" data-bind="scope: 'qty_change'">
 
    <button data-bind="click: decreaseQty">-</button>
 
    <input  data-bind="value: qty()"
            type="number"
            name="qty"
            id="qty"
            maxlength="12"
            title="<?php /* @escapeNotVerified */ echo __('Qty') ?>" class="input-text qty"
            data-validate="<?php echo $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>"
        />
 
    <button data-bind="click: increaseQty">+</button>
</div>

我们在输入字段data-bind的外部div和删除的默认value属性中添加了一个data-bind属性,并添加了我们自己属性。
可以把它想象data-bind成一种将HTML连接到我们组件的javascript函数的方法。因此,我们将div及其中的所有内容绑定到我们的组件(qty_change)。这意味着在那里调用的每个变量或函数将在我们的组件代码中进行搜索。这使得data-bind="value: qty()"现在更清楚:input元素的值链接到qty()我们组件中的调用结果
这里还有两个新按钮,通过click事件(data-bind="click: increaseQty"链接到我们的组件

现在,最后一步:组件。

位于/Magease/QtyIncrementors/view/frontend/web/js/view/product/view/qty_change.js,它具有以下内容:

define([
    'ko',
    'uiComponent'
], function (ko, Component) {
    'use strict';
 
    return Component.extend({
        initialize: function () {
            //initialize parent Component
            this._super();
            this.qty = ko.observable(this.defaultQty);
        },
 
        decreaseQty: function() {
            var newQty = this.qty() - 1;
            if (newQty < 1) {
                newQty = 1;
            }
            this.qty(newQty);
        },
 
        increaseQty: function() {
            var newQty = this.qty() + 1;
            this.qty(newQty);
        }
 
    });
});

现在一切都清楚多了,initialize函数中,我们有一个qty变量(实际上是一个可观察的变量,它是一个knockout.js的东西),当像函数一样调用它时返回其值(因此data-bind="value: qty()")。此外,有两种方法(decreaseQtyincreaseQty)在单击按钮时修改此变量(请记住data-bind="click: increaseQty"?)。

如果你尝试刷新页面,没有任何反应,因为我们忘记更改默认addtocart.phtml模板,即Magento不知道我们想要使用我们自己的模板,所以我们必须在布局中更改模板路径。现在,创建一个新的xml文件/Magease/QtyIncrementors/view/frontend/layout/catalog_product_view.xml

这是文件内容:

<?xml version="1.0"?>
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="product.info.addtocart">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">Magease_QtyIncrementors::catalog/product/view/addtocart.phtml</argument>
            </action>
        </referenceBlock>
        <referenceBlock name="product.info.addtocart.additional">
            <action method="setTemplate">
                <argument name="template" xsi:type="string">Magease_QtyIncrementors::catalog/product/view/addtocart.phtml</argument>
            </action>
        </referenceBlock>
    </body>
</page>

我们在这里引用了两个块 - product.info.addtocart用于简单的产品,product.info.addtocart.additional用于可配置产品。我们需要做的就是更改模板 - 我们使用自己的模板(来自我们的模块),而不是使用默认模板。通过这种方式,您也可以轻松更改分组和捆绑产品的模板。要实现分组或捆绑产品的qty增量,可以使用相同的组件,只要确保为每个输入字段实例化它即可

注意:如果要覆盖主题中的文件,最好在主题中执行更改,而不是在模块中。

和往常一样,我们准备了一个可以通过composer安装的模块:

添加模块作为依赖项:

composer config repositories.magease_qtyincrementors vcs git@bitbucket.org:lurajcevi/magease_qtyincrementors.git

要求Composer下载它:

composer require magease/qty_incrementors:dev-master

如果Composer要求您提供一组凭据,请按照这些说明操作

当composer完成他的工作时,我们可以启用我们的模块:

bin/magento module:enable Magease_QtyIncrementors

然后

bin/magento setup:upgrade

我们的模块已启用,我们可以使用它了。