Shopify结合Vue.js切换商品变体时报Cannot read 'length'属性错误
报错根因
该报错的核心是Shopify.Product.getVariantById方法尝试读取商品的variants数组的length属性时,传入的商品对象不符合预期,要么不存在、要么没有variants字段,导致读取undefined的length触发报错。
具体触发原因
- 1、
Shopify.OptionSelectors重复实例化:你把实例化逻辑写在了下拉框的change事件里,每次切换选项都会新建实例,会导致Shopify内置js的内部状态冲突混乱。 - 2、异步数据加载时序问题:你初始化存储商品数据的
data字段时赋值为空字符串,axios是异步请求,当下拉change事件触发早于接口返回时,this.data还是空字符串,传入OptionSelectors的product参数不是合法的Shopify商品对象,缺少variants字段。 - 3、回调函数this指向错误:
onVariantSelected传入的this.selectCallback没有绑定this指向,回调执行时内部的this不是Vue实例,会导致后续赋值失败。
推荐解决方案(无需调用Shopify内置OptionSelectors)
你已经通过Liquid渲染了所有可用变体的option,value直接是variant id,切换的时候直接取选中值赋值即可,完全不需要引入Shopify的内置方法,逻辑更简单不会报错:
直接修改changeVariants方法:
changeVariants() { // 直接取下拉框选中的variant id赋值 this.productData.id = this.productSelect.value // 如果需要获取更多变体信息,直接从商品数据里过滤即可 const currentVariant = this.data.variants?.find(v => v.id == this.productData.id) if (currentVariant) { // 可在这里更新价格、库存等其他展示信息 } }
兼容Shopify.OptionSelectors的修正方案
如果你一定要使用Shopify内置的选择器能力,可按以下步骤修正:
- 调整data字段配置,修改命名避免混淆,新增初始化标记:
data() { return { product: null, // 原来存储商品数据的data字段改名为product,避免和Vue内置属性冲突 productSelect: '', productQuantity: 1, productData: {}, optionSelectorInited: false }; },
- 修改axios请求逻辑,拿到完整商品数据后再初始化选择器,仅初始化一次:
created() { axios .get(`${window.location.href}.js`) .then((res) => { this.product = res.data; // 数据加载完成后再初始化选择器 this.initOptionSelector() }) .catch((err) => { console.log(err); }); },
- 新增选择器初始化方法,绑定回调的this指向:
methods: { initOptionSelector() { // 确保商品数据和变体字段存在再初始化 if (!this.product?.variants?.length) return new Shopify.OptionSelectors('product-select', { product: this.product, onVariantSelected: this.selectCallback.bind(this), // 绑定this指向Vue实例 enableHistoryState: true, }); this.optionSelectorInited = true }, // 原有changeVariants方法可以直接删除,OptionSelectors会自动监听选择事件 }
- 移除select标签上的
v-on:change="changeVariants"绑定即可。
内容的提问来源于stack exchange,提问作者i'm fat.
相关产品推荐
相关产品推荐

