Shopify Storefront API GraphQL如何获取选中产品的特定数据
实现方案
你的现有代码存在4个核心问题,会导致无法正确匹配选中产品、拿不到元字段数据:
- 初始查询产品列表的GraphQL语句没有请求
metafields字段,接口不会返回元字段数据 - 生成下拉选项时
<option>标签闭合错误,写成了开标签<option>会导致DOM结构异常 - 选择事件中获取选中值的逻辑错误:
$(this).find('option').val()永远取第一个选项的值,无法拿到当前选中项 - 选择事件触发后遍历全量产品追加所有产品标题,既没有匹配选中项,也没有清空上一次选择的渲染结果
方案1:首屏拉取全量产品+元字段(适合产品数≤250的场景)
你当前设置的products(first:250)刚好是Shopify Storefront API单请求拉取产品的上限,产品量不大的话可以首屏直接把所有产品的元字段一起拉回,选中时直接从本地缓存的接口返回值里匹配即可,不需要额外发请求。
首先修改产品查询的GraphQL语句,补充metafields字段,注意要指定你需要的元字段命名空间(比如Shopify后台自定义元字段默认命名空间是custom):
{ products(first: 250) { edges { node { id handle title metafields(first: 20, namespace: "custom") { edges { node { key value type } } } } } } }
如果你需要拉取其他命名空间的元字段,替换
namespace的值即可;不指定namespace会返回当前访问令牌有权限读取的所有元字段。
修正后的完整代码如下:
function apiCall(productQuery) { return fetch('https://store//api/2022-04/graphql.json', { method: 'POST', headers: { 'Content-Type': 'application/graphql', 'X-Shopify-Storefront-Access-Token': "xxx" }, body: productQuery } ) .then(response => response.json()); } function getProducts() { const productQuery = `{ products(first: 250) { edges { node { id handle title metafields(first: 20, namespace: "custom") { edges { node { key value type } } } } } } }`; return apiCall(productQuery); } $(document).ready(function() { const product_selector_container = $('.product_selector_container'); getProducts().then(response => { product_selector_container.prepend("<select name='product_compatibility_selector' id='product_compatibility_selector'></select>"); const productSelect = $('#product_compatibility_selector'); const productSelectResult = $("#product_compatibility_result"); response.data.products.edges.forEach(product => { // 修正option标签闭合错误 const optionValues = `<option value="${product.node.handle}">${product.node.title}</option>`; productSelect.append(optionValues); }); $("#product_compatibility_selector").on('change', function() { // 正确获取当前选中项的标题和handle const selectedTitle = $(this).find('option:selected').text(); const selectedHandle = $(this).val(); $(".chosen_product_title").text(selectedTitle); // 匹配当前选中的产品 const selectedProductEdge = response.data.products.edges.find(edge => edge.node.handle === selectedHandle); // 清空上一次渲染的结果 productSelectResult.empty(); if (!selectedProductEdge) return; const selectedProduct = selectedProductEdge.node; // 渲染元字段,可按需调整展示格式 let metafieldsHtml = '<ul class="product-metafields">'; selectedProduct.metafields.edges.forEach(metafieldEdge => { const mf = metafieldEdge.node; metafieldsHtml += `<li><strong>${mf.key}:</strong> ${mf.value}</li>` }) metafieldsHtml += '</ul>'; productSelectResult.append(metafieldsHtml); }); }); });
方案2:选中后单独请求单个产品元字段(适合产品量大的场景)
如果产品数多、元字段数据量大,首屏全量拉取会拖慢加载速度,可以不在初始查询中携带metafields字段,等用户选中产品时,单独发请求查询对应产品的元字段即可。
单个产品按handle查询的GraphQL示例:
{ productByHandle(handle: "选中产品的handle值") { title metafields(first: 20, namespace: "custom") { edges { node { key value type } } } } }
选中事件触发时拿到选中项的handle,调用apiCall传入上述查询语句,拿到返回结果后渲染到页面即可。
内容的提问来源于stack exchange,提问作者Mathijs Delva
相关产品推荐
相关产品推荐

