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
相关产品推荐
相关产品推荐

