You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Magento 2中用Knockout.js实现选中配送方式的信息展示

问题:Magento 2中用Knockout.js实现选中配送方式的动态汇总展示

我是Knockout.js新手,觉得它上手难度较高,之前用jQuery轻松实现的功能在Knockout.js里没法直接照搬。我在Magento 2店铺里,想实现选中配送方式后,在汇总框里动态展示该配送方式的名称、时间范围、价格等信息。

目前Magento已经用checked绑定把选中的配送方式同步到了quote中,每个配送方式的输入元素还带有自定义数据(比如配送名称、时间范围),我想要的汇总展示效果如下:

<div id="selected-method-summary">
    <span class="method-name" data-bind="text: selectedMethod.name"></span>
    <span class="method-timerange" data-bind="text: selectedMethod.timerange"></span>
    <span class="method-price" data-bind="text: selectedMethod.price"></span>
</div>

<fieldset class="fieldset rate" data-bind="visible: (rates().length > 0)">
    <dl class="items methods" data-bind="foreach: shippingRateGroups, mageInit: {'accordion':{'openedState': 'active', 'collapsible': true, 'active': [2], 'multipleCollapsible': true}} ">
        <div class="method-group" attr="'id': $data" data-role="collapsible">
            <dt class="item-title" data-role="title"><span data-bind="text: $data"></span> <span class="accordion-toggle"></span></dt>
            <dd class="item-options" data-role="content" attr="'id': $data + 'content'" data-bind="foreach: { data:$parent.getRatesForGroup($data), as: 'method' }">
                <div click="element.selectShippingMethod" attr="'data-date': method.extension_attributes.date, 'data-timerange': method.extension_attributes.time_range" data-bind="css: {'field choice item': available, 'message error': !available} ">
                    <!-- ko ifnot: (available) -->
                    <div data-bind="text: error_message"></div>
                    <!-- /ko -->
                    <!-- ko if: (available) -->
                    <input type="radio"
                            class="radio"
                            data-bind="
                click: $parents[1].selectShippingMethod,
                checked: element.isSelected,
                attr: {
                        value: carrier_code + '_' + method_code,
                        id: 's_method_' + carrier_code + '_' + method_code
                        }
                "/>
                    <label class="label" data-bind="attr: {for: 's_method_' + carrier_code + '_' + method_code}">
                        <!-- ko text: $data.method_title --><!-- /ko -->
                        <each args="element.getRegion('price')" render="" />
                    </label>
                    <!-- /ko -->
                </div>
            </dd>
        </div>
    </dl>
</fieldset>

现在的问题是,data-bind="checked: element.isSelected"只返回一个拼接的carrier_code_method_code值,对应的计算属性代码如下:

isSelected: ko.computed(function () {
            return quote.shippingMethod() ?
                quote.shippingMethod()['carrier_code'] + '_' + quote.shippingMethod()['method_code'] :
                null;
        }),

我想扩展这个功能,让汇总框能动态展示选中配送方式的详细数据,但又怕修改原有代码会破坏Magento的默认功能,请问该怎么实现?


解决方案

1. 新增selectedMethod可观察对象,不修改原有isSelected

不要直接修改Magento自带的isSelected计算属性,而是在对应的ViewModel里新增一个selectedMethod可观察对象,用来存储选中配送方式的完整数据:

// 在ViewModel的初始化函数里添加
this.selectedMethod = ko.observable(null);

// 监听quote.shippingMethod的变化,同步更新selectedMethod
var self = this;
quote.shippingMethod.subscribe(function(newShippingMethod) {
    if (newShippingMethod) {
        // 从所有配送方式中找到匹配的完整数据
        var matchedMethod = null;
        // 遍历所有配送组
        ko.utils.arrayForEach(self.shippingRateGroups(), function(group) {
            var rates = self.getRatesForGroup(group);
            matchedMethod = ko.utils.arrayFirst(rates, function(rate) {
                return rate.carrier_code + '_' + rate.method_code === newShippingMethod.carrier_code + '_' + newShippingMethod.method_code;
            });
            if (matchedMethod) return;
        });
        if (matchedMethod) {
            // 组装需要展示的数据,包含自定义属性
            self.selectedMethod({
                name: matchedMethod.method_title,
                timerange: matchedMethod.extension_attributes?.time_range || '',
                price: matchedMethod.price_formatted || '' // 这里用Magento格式化后的价格
            });
        } else {
            self.selectedMethod(null);
        }
    } else {
        self.selectedMethod(null);
    }
});

2. 优化汇总框的绑定逻辑

为避免selectedMethod为空时出现报错,给汇总框添加if绑定,并调整内部数据绑定的写法:

<div id="selected-method-summary" data-bind="if: selectedMethod()">
    <span class="method-name" data-bind="text: selectedMethod().name"></span>
    <span class="method-timerange" data-bind="text: selectedMethod().timerange"></span>
    <span class="method-price" data-bind="text: selectedMethod().price"></span>
</div>

3. 用Magento Mixins扩展ViewModel(不修改核心代码)

在Magento 2中,不要直接修改核心模块的ViewModel文件,应该用mixins来扩展对应的ViewModel(比如Magento_Checkout/js/view/shipping):

  1. 创建自定义模块,在requirejs-config.js中配置mixin:
var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/view/shipping': {
                'Your_Module/js/view/shipping-mixin': true
            }
        }
    }
};
  1. 编写shipping-mixin.js文件:
define([
    'ko',
    'Magento_Checkout/js/model/quote'
], function(ko, quote) {
    'use strict';

    return function (shippingViewModel) {
        // 新增selectedMethod可观察对象
        shippingViewModel.selectedMethod = ko.observable(null);

        // 监听quote.shippingMethod变化
        quote.shippingMethod.subscribe(function(newShippingMethod) {
            if (newShippingMethod) {
                var matchedMethod = null;
                ko.utils.arrayForEach(shippingViewModel.shippingRateGroups(), function(group) {
                    var rates = shippingViewModel.getRatesForGroup(group);
                    matchedMethod = ko.utils.arrayFirst(rates, function(rate) {
                        return rate.carrier_code + '_' + rate.method_code === newShippingMethod.carrier_code + '_' + newShippingMethod.method_code;
                    });
                    if (matchedMethod) return;
                });
                if (matchedMethod) {
                    shippingViewModel.selectedMethod({
                        name: matchedMethod.method_title,
                        timerange: matchedMethod.extension_attributes?.time_range || '',
                        price: matchedMethod.price_formatted || ''
                    });
                } else {
                    shippingViewModel.selectedMethod(null);
                }
            } else {
                shippingViewModel.selectedMethod(null);
            }
        });

        // 初始化时触发一次,确保已有选中项时能显示数据
        if (quote.shippingMethod()) {
            quote.shippingMethod.notifySubscribers(quote.shippingMethod());
        }

        return shippingViewModel;
    };
});

这种方式完全不会修改Magento的核心代码,既实现了需求,又保证了系统的可维护性和兼容性。


内容的提问来源于stack exchange,提问作者schnacks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 04:55:40