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

Shopify Liquid与JS间传递选中商品数据实现商品对比求助

解决Liquid与JS传递商品数据的方案

一、先修正Liquid中的商品标识与数据存储

你原来用counterUomo作为data-id不太稳妥,刷新页面或商品顺序变化时计数会混乱,直接用Shopify商品的唯一id或handle才可靠。同时可以把需要对比的商品特性直接存在元素的data-*属性里,或者提前把所有商品的对比数据渲染成JSON供JS调用。

修改后的Liquid商品展示代码

<div class="collection-uomo">
    <div class="compare-products">
        <h3>MAN</h3>
        {% for product in collections.all.products %}
            {% for collection in product.collections %}
                {% if collection.title == 'MAN' %} 
                    <div class="compare-product" data-product-id="{{ product.id }}" data-product-data='{
                        "title": "{{ product.title | escape }}",
                        "image": "{{ product.featured_image | product_img_url: "medium" }}",
                        "price": "{{ product.price | money }}",
                        "vendor": "{{ product.vendor | escape }}",
                        "material": "{{ product.metafields.custom.material | default: "N/A" }}"
                    }'>
                        <img src="{{ product.featured_image | product_img_url: 'medium' }}" title="{{ product.title | escape }}"/>
                        <h6 class="product-title">{{ product.title | escape }}</h6>
                    </div>
                {% endif %}
            {% endfor %}
        {% endfor %}
    </div>
</div>

<!-- 可选:提前渲染全局商品数据JSON,方便JS快速调用 -->
<script type="application/json" id="man-products-data">
    [
        {% for product in collections.all.products %}
            {% for collection in product.collections %}
                {% if collection.title == 'MAN' %}
                    {
                        "id": "{{ product.id }}",
                        "title": "{{ product.title | escape }}",
                        "image": "{{ product.featured_image | product_img_url: 'medium' }}",
                        "price": "{{ product.price | money }}",
                        "vendor": "{{ product.vendor | escape }}",
                        "material": "{{ product.metafields.custom.material | default: 'N/A' }}"
                    }{% unless forloop.last and forloop.parentloop.last %},{% endunless %}
                {% endif %}
            {% endfor %}
        {% endfor %}
    ]
</script>

二、JS端获取选中商品并生成对比表格

方案1:点击时直接从data属性读取商品数据

适合不需要频繁查询的场景,点击商品时直接提取元素上的data-product-data:

// 存储选中的商品
let selectedProducts = [];
const maxSelect = 3; // 最多选3件

// 绑定商品点击事件
document.querySelectorAll('.compare-product').forEach(item => {
    item.addEventListener('click', function() {
        const productData = JSON.parse(this.dataset.productData);
        const productId = this.dataset.productId;

        // 判断是否已选中该商品
        const isSelected = selectedProducts.some(p => p.id === productId);
        if (isSelected) {
            // 取消选中
            selectedProducts = selectedProducts.filter(p => p.id !== productId);
            this.classList.remove('selected');
        } else {
            // 超过数量限制提示
            if (selectedProducts.length >= maxSelect) {
                alert('最多只能选择3件商品进行对比');
                return;
            }
            // 添加选中
            selectedProducts.push({...productData, id: productId});
            this.classList.add('selected');
        }

        // 更新对比表格
        renderCompareTable(selectedProducts);
    });
});

// 生成对比表格的函数
function renderCompareTable(products) {
    const tableContainer = document.getElementById('compare-table-container');
    if (products.length < 2) {
        tableContainer.innerHTML = '';
        return;
    }

    // 构建表格HTML
    let tableHtml = '<table><thead><tr><th>特性</th>';
    // 表头:商品名称+缩略图
    products.forEach(p => {
        tableHtml += `<th><img src="${p.image}" alt="${p.title}" width="80"/><br>${p.title}</th>`;
    });
    tableHtml += '</tr></thead><tbody>';

    // 表格内容:逐一展示特性
    const features = [
        {label: '价格', key: 'price'},
        {label: '品牌', key: 'vendor'},
        {label: '材质', key: 'material'}
        // 可添加更多需要对比的特性
    ];

    features.forEach(feature => {
        tableHtml += `<tr><td>${feature.label}</td>`;
        products.forEach(p => {
            tableHtml += `<td>${p[feature.key]}</td>`;
        });
        tableHtml += '</tr>';
    });

    tableHtml += '</tbody></table>';
    tableContainer.innerHTML = tableHtml;
}

方案2:从全局JSON读取商品数据

如果需要更灵活的操作(比如批量处理),直接读取页面预先渲染的JSON数据:

// 获取全局商品数据
const allManProducts = JSON.parse(document.getElementById('man-products-data').textContent);
let selectedProducts = [];
const maxSelect = 3;

// 点击事件逻辑
document.querySelectorAll('.compare-product').forEach(item => {
    item.addEventListener('click', function() {
        const productId = this.dataset.productId;
        // 从全局数据中匹配对应商品
        const product = allManProducts.find(p => p.id === productId);
        if (!product) return;

        const isSelected = selectedProducts.some(p => p.id === productId);
        if (isSelected) {
            selectedProducts = selectedProducts.filter(p => p.id !== productId);
            this.classList.remove('selected');
        } else {
            if (selectedProducts.length >= maxSelect) {
                alert('最多只能选择3件商品进行对比');
                return;
            }
            selectedProducts.push(product);
            this.classList.add('selected');
        }

        renderCompareTable(selectedProducts);
    });
});

// renderCompareTable函数与方案1一致,此处省略

三、关键注意事项

  • 用product.id作为唯一标识比自定义计数器可靠,Shopify商品ID永久唯一
  • 渲染JSON时用escape过滤器处理特殊字符,避免解析错误
  • 商品的自定义特性(如材质、尺寸)可通过product.metafields.namespace.key获取
  • 给选中的商品添加selected类做视觉区分,提升用户体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:45:31