Shopify主题开发:默认选中首个可用商品变体对应单选按钮
问题根源
当前代码默认选中最后一个变体的核心原因是:在Liquid循环输出单选按钮时,给同组下所有单选按钮都添加了checked属性。对于相同name的单选按钮组,浏览器会默认选中最后一个携带checked属性的元素,和预期选中第一个可用变体的逻辑冲突。
修复方案
- 移除单选按钮循环中硬编码的
checked属性,不再在渲染阶段直接给所有选项加选中状态 - 页面加载完成后,自动匹配第一个
available: true的可用变体,选中其对应的所有选项值 - 抽离价格更新逻辑为公共函数,页面初始化、用户切换选项时都可以调用,避免重复代码
- 修正原逻辑中未判断变体可用状态的问题,避免选中缺货变体
修复后完整代码
<!-- 存储变体JSON数据 --> <script id="variants" type="application/json"> {{ product.variants | json }} </script> <script> var variantsArray = JSON.parse(document.getElementById("variants").text); // 抽离价格更新公共方法 function updatePriceBySelectedOptions() { var checkedValues = document.querySelectorAll('input[type="radio"]:checked'); var checkedArray = Array.from(checkedValues, radio => radio.value); for (let l = 0; l < variantsArray.length; l++) { // 匹配选中选项对应的变体 if (JSON.stringify(checkedArray) == JSON.stringify(variantsArray[l].options)) { var priceString = variantsArray[l].price.toString(); document.querySelector('.unit-price').textContent = `$${priceString.substr(0, priceString.length - 2)}`; // 可在这里扩展变体缺货判断、库存提示等逻辑 break; } } } </script> <span class="unit-price">{{ price | money }}</span> <div class="radios"> {% for product_option in product.options_with_values %} <h4 class="options-title">{{ product_option.name }}</h4> <div class="options-values"> {% for value in product_option.values %} <!-- 移除所有硬编码的checked属性 --> <input type="radio" id="{{ value | handle }}" name="{{ product_option.name}}" value="{{ value }}"> <label for="{{ value | handle }}">{{ value }}</label> {% endfor %} </div> <div class="line"></div> {% endfor %} <script> var radioArray = document.querySelectorAll('input[type="radio"]'); // 查找第一个可用变体,无可用变体时回退选中第一个变体 var firstAvailableVariant = variantsArray.find(variant => variant.available) || variantsArray[0]; // 页面初始化时选中第一个可用变体的对应选项 firstAvailableVariant.options.forEach((optionValue, index) => { let optionName = document.querySelectorAll('.options-title')[index].textContent; let targetRadio = document.querySelector(`input[name="${optionName}"][value="${optionValue}"]`); if (targetRadio) targetRadio.checked = true; }); // 初始化默认价格 updatePriceBySelectedOptions(); // 绑定选项切换事件 for (let k = 0; k < radioArray.length; k++) { radioArray[k].addEventListener('change', updatePriceBySelectedOptions); } </script> </div>
额外优化点
- 给单选按钮的id加了
handle过滤器,避免选项值带特殊字符(比如空格、斜杠)时id不合法导致label关联失效 - 匹配到对应变体后加了
break,找到目标后终止循环减少不必要的遍历 - 增加无可用变体的兜底逻辑,避免页面加载后无单选按钮被选中的异常情况
内容的提问来源于stack exchange,提问作者avocado
相关产品推荐
相关产品推荐

