Skip to Content
🎉 探索 Shopify 的无限可能 结构化知识 + 实战案例,持续更新中...
Liquid 开发产品对象详解

产品对象详解

产品对象是 Shopify Liquid 中最重要和最复杂的对象之一。它包含了商品的所有信息,包括基本属性、变体、图片、选项等。掌握产品对象的使用对于构建功能完整的电商主题至关重要。

产品基本属性

基础信息

<!-- 产品基本信息 --> <div class="product-info" itemscope itemtype="http://schema.org/Product"> <h1 itemprop="name">{{ product.title }}</h1> <div class="product-meta"> <p class="vendor">品牌: <span itemprop="brand">{{ product.vendor }}</span></p> <p class="product-type">分类: {{ product.type }}</p> <p class="sku" itemprop="sku">SKU: {{ product.selected_or_first_available_variant.sku }}</p> </div> <div class="product-description" itemprop="description"> {{ product.description }} </div> </div>

价格信息

<!-- 产品价格展示 --> <div class="product-price" itemscope itemtype="http://schema.org/Offer"> {% assign current_variant = product.selected_or_first_available_variant %} <meta itemprop="priceCurrency" content="{{ shop.currency }}"> <meta itemprop="price" content="{{ current_variant.price | money_without_currency }}"> {% if current_variant.compare_at_price > current_variant.price %} <span class="price-compare"> 原价: <s>{{ current_variant.compare_at_price | money }}</s> </span> <span class="price-current sale"> 现价: {{ current_variant.price | money }} </span> <span class="price-save"> 节省: {{ current_variant.compare_at_price | minus: current_variant.price | money }} ({{ current_variant.compare_at_price | minus: current_variant.price | times: 100 | divided_by: current_variant.compare_at_price }}% OFF) </span> {% else %} <span class="price-current"> {{ current_variant.price | money }} </span> {% endif %} {% comment %} 价格范围显示 {% endcomment %} {% unless product.has_only_default_variant %} <div class="price-range"> {% if product.price_varies %} <span>价格范围: {{ product.price_min | money }} - {{ product.price_max | money }}</span> {% endif %} {% if product.compare_at_price_varies %} <span>原价范围: {{ product.compare_at_price_min | money }} - {{ product.compare_at_price_max | money }}</span> {% endif %} </div> {% endunless %} </div>

库存状态

<!-- 库存信息 --> <div class="product-availability"> {% assign current_variant = product.selected_or_first_available_variant %} {% if current_variant.available %} <span class="in-stock" itemprop="availability" content="http://schema.org/InStock"> {% if current_variant.inventory_management %} {% if current_variant.inventory_quantity > 0 %} 有库存 ({{ current_variant.inventory_quantity }} 件) {% else %} 有库存 {% endif %} {% else %} 有库存 {% endif %} </span> {% else %} <span class="out-of-stock" itemprop="availability" content="http://schema.org/OutOfStock"> 缺货 </span> {% endif %} {% comment %} 低库存警告 {% endcomment %} {% if current_variant.inventory_quantity <= 5 and current_variant.inventory_quantity > 0 %} <div class="low-stock-warning"> 仅剩 {{ current_variant.inventory_quantity }} 件! </div> {% endif %} </div>

产品图片

主图展示

<!-- 产品主图 --> <div class="product-images"> {% assign featured_image = product.featured_image | default: product.images.first %} {% if featured_image %} <div class="main-image"> <img src="{{ featured_image | img_url: '800x800' }}" srcset="{{ featured_image | img_url: '400x400' }} 400w, {{ featured_image | img_url: '600x600' }} 600w, {{ featured_image | img_url: '800x800' }} 800w, {{ featured_image | img_url: '1000x1000' }} 1000w" sizes="(max-width: 768px) 100vw, 50vw" alt="{{ featured_image.alt | default: product.title }}" itemprop="image" loading="lazy" /> </div> {% endif %} </div>

图片画廊

<!-- 产品图片画廊 --> <div class="product-gallery"> {% if product.images.size > 1 %} <div class="thumbnail-list"> {% for image in product.images %} <button class="thumbnail {% if forloop.first %}active{% endif %}" data-image-id="{{ image.id }}" type="button"> <img src="{{ image | img_url: '100x100' }}" alt="{{ image.alt | default: product.title }}" loading="lazy" /> </button> {% endfor %} </div> <div class="main-gallery"> {% for image in product.images %} <div class="gallery-image {% if forloop.first %}active{% endif %}" data-image-id="{{ image.id }}"> <img src="{{ image | img_url: '800x800' }}" srcset="{{ image | img_url: '400x400' }} 400w, {{ image | img_url: '600x600' }} 600w, {{ image | img_url: '800x800' }} 800w, {{ image | img_url: '1200x1200' }} 1200w" sizes="(max-width: 768px) 100vw, 60vw" alt="{{ image.alt | default: product.title }}" loading="lazy" /> </div> {% endfor %} </div> {% endif %} </div>

变体关联图片

<!-- 变体图片映射 --> <div class="variant-images"> {% for variant in product.variants %} {% if variant.featured_image %} <div class="variant-image" data-variant-id="{{ variant.id }}" style="display: none;"> <img src="{{ variant.featured_image | img_url: '800x800' }}" alt="{{ variant.title }}" loading="lazy" /> </div> {% endif %} {% endfor %} </div> <script> // 变体切换时更新图片 document.addEventListener('DOMContentLoaded', function() { const variantSelector = document.querySelector('[name="id"]') if (variantSelector) { variantSelector.addEventListener('change', function() { const variantId = this.value const variantImage = document.querySelector(`[data-variant-id="${variantId}"]`) // 隐藏所有变体图片 document.querySelectorAll('.variant-image').forEach(img => { img.style.display = 'none' }) // 显示当前变体图片 if (variantImage) { variantImage.style.display = 'block' } }) } }) </script>

产品变体

基本变体信息

<!-- 产品变体选择 --> <div class="product-variants"> {% unless product.has_only_default_variant %} {% for option in product.options_with_values %} <div class="variant-option"> <label for="option-{{ option.position }}">{{ option.name }}:</label> {% if option.name == 'Color' or option.name == '颜色' %} <!-- 颜色选择器 --> <div class="color-swatches"> {% for value in option.values %} {% assign option_id = 'option-' | append: option.position | append: '-' | append: forloop.index %} <input type="radio" id="{{ option_id }}" name="options[{{ option.name }}]" value="{{ value }}" {% if option.selected_value == value %}checked{% endif %}> <label for="{{ option_id }}" class="color-swatch" style="background-color: {{ value | downcase }}" title="{{ value }}"> <span class="sr-only">{{ value }}</span> </label> {% endfor %} </div> {% elsif option.name == 'Size' or option.name == '尺寸' %} <!-- 尺寸选择器 --> <div class="size-options"> {% for value in option.values %} {% assign option_id = 'option-' | append: option.position | append: '-' | append: forloop.index %} <input type="radio" id="{{ option_id }}" name="options[{{ option.name }}]" value="{{ value }}" {% if option.selected_value == value %}checked{% endif %}> <label for="{{ option_id }}" class="size-option"> {{ value }} </label> {% endfor %} </div> {% else %} <!-- 下拉选择器 --> <select name="options[{{ option.name }}]" id="option-{{ option.position }}"> {% for value in option.values %} <option value="{{ value }}" {% if option.selected_value == value %}selected{% endif %}> {{ value }} </option> {% endfor %} </select> {% endif %} </div> {% endfor %} {% endunless %} </div>

变体数据映射

<!-- 变体数据 JSON --> <script type="application/json" id="product-variants"> { "variants": [ {% for variant in product.variants %} { "id": {{ variant.id }}, "title": "{{ variant.title | escape }}", "sku": "{{ variant.sku | escape }}", "price": {{ variant.price }}, "compare_at_price": {% if variant.compare_at_price %}{{ variant.compare_at_price }}{% else %}null{% endif %}, "available": {{ variant.available | json }}, "inventory_quantity": {% if variant.inventory_quantity %}{{ variant.inventory_quantity }}{% else %}null{% endif %}, "inventory_management": {% if variant.inventory_management %}"{{ variant.inventory_management }}"{% else %}null{% endif %}, "weight": {{ variant.weight }}, "weight_unit": "{{ variant.weight_unit }}", "featured_image": {% if variant.featured_image %}"{{ variant.featured_image | img_url: '800x800' }}"{% else %}null{% endif %}, "options": [ {% for option in variant.options %} "{{ option | escape }}"{% unless forloop.last %},{% endunless %} {% endfor %} ] }{% unless forloop.last %},{% endunless %} {% endfor %} ], "options": [ {% for option in product.options %} { "name": "{{ option | escape }}", "position": {{ forloop.index }}, "values": [ {% assign option_values = product.options_with_values[forloop.index0].values %} {% for value in option_values %} "{{ value | escape }}"{% unless forloop.last %},{% endunless %} {% endfor %} ] }{% unless forloop.last %},{% endunless %} {% endfor %} ] } </script>

动态变体选择

<!-- 智能变体选择器 --> <div class="smart-variant-selector"> {% for option in product.options_with_values %} <div class="option-group" data-option-position="{{ option.position }}"> <h4>{{ option.name }}:</h4> <div class="option-values"> {% for value in option.values %} {% assign available_in_option = false %} {% for variant in product.variants %} {% if variant.option1 == value or variant.option2 == value or variant.option3 == value %} {% if variant.available %} {% assign available_in_option = true %} {% break %} {% endif %} {% endif %} {% endfor %} <button type="button" class="option-value {% unless available_in_option %}unavailable{% endunless %}" data-value="{{ value }}" {% unless available_in_option %}disabled{% endunless %}> {{ value }} {% unless available_in_option %} <span class="unavailable-text">(缺货)</span> {% endunless %} </button> {% endfor %} </div> </div> {% endfor %} </div>

产品标签和分类

标签处理

<!-- 产品标签 --> <div class="product-tags"> {% if product.tags.size > 0 %} <h4>标签:</h4> <div class="tag-list"> {% for tag in product.tags %} <a href="{{ blog.url }}/tagged/{{ tag | handle }}" class="tag" rel="tag"> {{ tag }} </a> {% endfor %} </div> {% endif %} </div> <!-- 基于标签的功能 --> <div class="product-features"> {% if product.tags contains 'new' %} <span class="badge new">新品</span> {% endif %} {% if product.tags contains 'sale' %} <span class="badge sale">促销</span> {% endif %} {% if product.tags contains 'limited' %} <span class="badge limited">限量</span> {% endif %} {% if product.tags contains 'eco-friendly' %} <span class="badge eco">环保</span> {% endif %} </div>

集合关联

<!-- 产品所属集合 --> <div class="product-collections"> {% if product.collections.size > 0 %} <h4>分类:</h4> <nav class="collection-breadcrumb"> {% for collection in product.collections %} <a href="{{ collection.url }}">{{ collection.title }}</a> {% unless forloop.last %} / {% endunless %} {% endfor %} </nav> {% endif %} </div>

产品元字段

自定义字段

<!-- 产品元字段 --> <div class="product-metafields"> {% comment %} 材质信息 {% endcomment %} {% if product.metafields.custom.material %} <div class="metafield-item"> <h4>材质:</h4> <p>{{ product.metafields.custom.material.value }}</p> </div> {% endif %} {% comment %} 尺寸指南 {% endcomment %} {% if product.metafields.custom.size_guide %} <div class="metafield-item"> <h4>尺寸指南:</h4> <div class="size-guide"> {{ product.metafields.custom.size_guide.value }} </div> </div> {% endif %} {% comment %} 护理说明 {% endcomment %} {% if product.metafields.custom.care_instructions %} <div class="metafield-item"> <h4>护理说明:</h4> <div class="care-instructions"> {{ product.metafields.custom.care_instructions.value }} </div> </div> {% endif %} {% comment %} 技术规格 {% endcomment %} {% if product.metafields.custom.specifications %} <div class="metafield-item"> <h4>技术规格:</h4> <div class="specifications"> {{ product.metafields.custom.specifications.value }} </div> </div> {% endif %} </div>

结构化数据

<!-- 产品结构化数据 --> <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "Product", "name": "{{ product.title | escape }}", "description": "{{ product.description | strip_html | truncate: 200 | escape }}", "image": [ {% for image in product.images limit: 3 %} "{{ image | img_url: '800x800' }}"{% unless forloop.last %},{% endunless %} {% endfor %} ], "brand": { "@type": "Brand", "name": "{{ product.vendor | escape }}" }, "sku": "{{ product.selected_or_first_available_variant.sku }}", "mpn": "{{ product.selected_or_first_available_variant.barcode }}", "offers": { "@type": "Offer", "url": "{{ shop.url }}{{ product.url }}", "priceCurrency": "{{ shop.currency }}", "price": "{{ product.selected_or_first_available_variant.price | money_without_currency }}", {% if product.selected_or_first_available_variant.compare_at_price > product.selected_or_first_available_variant.price %} "priceValidUntil": "{{ 'now' | date: '%Y' | plus: 1 }}-12-31", {% endif %} "availability": "{% if product.selected_or_first_available_variant.available %}http://schema.org/InStock{% else %}http://schema.org/OutOfStock{% endif %}", "seller": { "@type": "Organization", "name": "{{ shop.name | escape }}" } } {% if product.metafields.reviews.rating %} ,"aggregateRating": { "@type": "AggregateRating", "ratingValue": "{{ product.metafields.reviews.rating.value }}", "ratingCount": "{{ product.metafields.reviews.count.value }}" } {% endif %} } </script>

高级产品功能

产品推荐

<!-- 相关产品推荐 --> <div class="related-products"> <h3>相关产品</h3> {% comment %} 基于标签的推荐 {% endcomment %} {% assign related_products = collections.all.products | where: 'tags', product.tags.first %} {% assign related_products = related_products | where: 'available' %} {% assign related_products = related_products | remove: product %} {% if related_products.size == 0 %} {% comment %} 基于类型的推荐 {% endcomment %} {% assign related_products = collections.all.products | where: 'type', product.type %} {% assign related_products = related_products | where: 'available' %} {% assign related_products = related_products | remove: product %} {% endif %} {% if related_products.size == 0 %} {% comment %} 基于供应商的推荐 {% endcomment %} {% assign related_products = collections.all.products | where: 'vendor', product.vendor %} {% assign related_products = related_products | where: 'available' %} {% assign related_products = related_products | remove: product %} {% endif %} {% if related_products.size > 0 %} <div class="product-grid"> {% for related_product in related_products limit: 4 %} <div class="product-card"> <a href="{{ related_product.url }}"> <img src="{{ related_product.featured_image | img_url: '300x300' }}" alt="{{ related_product.title }}" loading="lazy" /> <h4>{{ related_product.title }}</h4> <p class="price">{{ related_product.price | money }}</p> </a> </div> {% endfor %} </div> {% endif %} </div>

库存追踪

<!-- 库存监控 --> <div class="inventory-tracker" data-product-id="{{ product.id }}"> {% for variant in product.variants %} <div class="variant-inventory" data-variant-id="{{ variant.id }}" data-inventory="{{ variant.inventory_quantity }}" data-policy="{{ variant.inventory_policy }}"> {% if variant.inventory_management %} {% if variant.inventory_quantity <= 0 %} <span class="status out-of-stock">{{ variant.title }} - 缺货</span> {% elsif variant.inventory_quantity <= 5 %} <span class="status low-stock">{{ variant.title }} - 仅剩 {{ variant.inventory_quantity }} 件</span> {% else %} <span class="status in-stock">{{ variant.title }} - 有库存</span> {% endif %} {% else %} <span class="status available">{{ variant.title }} - 有货</span> {% endif %} </div> {% endfor %} </div>

购买按钮组

<!-- 产品购买区域 --> <div class="product-purchase"> <form action="/cart/add" method="post" enctype="multipart/form-data" class="product-form"> <!-- 变体选择器 --> <div class="variant-selector"> {% unless product.has_only_default_variant %} <select name="id" id="product-variants" class="variant-dropdown"> {% for variant in product.variants %} <option value="{{ variant.id }}" {% unless variant.available %}disabled{% endunless %} data-price="{{ variant.price | money }}" data-compare-price="{{ variant.compare_at_price | money }}" data-inventory="{{ variant.inventory_quantity }}"> {{ variant.title }} {% unless variant.available %} - 缺货{% endunless %} - {{ variant.price | money }} </option> {% endfor %} </select> {% else %} <input type="hidden" name="id" value="{{ product.variants.first.id }}"> {% endunless %} </div> <!-- 数量选择器 --> <div class="quantity-selector"> <label for="quantity">数量:</label> <div class="quantity-input"> <button type="button" class="quantity-decrease" aria-label="减少数量">-</button> <input type="number" id="quantity" name="quantity" value="1" min="1" class="quantity-field"> <button type="button" class="quantity-increase" aria-label="增加数量">+</button> </div> </div> <!-- 购买按钮 --> <div class="purchase-buttons"> <button type="submit" class="btn btn-primary add-to-cart" {% unless product.available %}disabled{% endunless %}> {% if product.available %} <span class="add-text">加入购物车</span> <span class="adding-text" style="display: none;">加入中...</span> {% else %} 缺货 {% endif %} </button> <!-- 立即购买按钮 --> {% if product.available %} <button type="button" class="btn btn-secondary buy-now"> 立即购买 </button> {% endif %} <!-- 收藏按钮 --> <button type="button" class="btn btn-outline wishlist-toggle" data-product-id="{{ product.id }}"> <span class="wishlist-add">收藏</span> <span class="wishlist-remove" style="display: none;">取消收藏</span> </button> </div> <!-- 购买保证 --> <div class="purchase-guarantees"> <div class="guarantee-item"> <span class="icon">🚚</span> <span>免费配送</span> </div> <div class="guarantee-item"> <span class="icon">↩️</span> <span>30天退货</span> </div> <div class="guarantee-item"> <span class="icon">🔒</span> <span>安全支付</span> </div> </div> </form> </div>

性能优化

图片懒加载

<!-- 性能优化的图片加载 --> <div class="product-images-optimized"> {% assign featured_image = product.featured_image %} <!-- 主图(立即加载) --> {% if featured_image %} <div class="hero-image"> <img src="{{ featured_image | img_url: '800x800' }}" srcset="{{ featured_image | img_url: '400x400' }} 400w, {{ featured_image | img_url: '600x600' }} 600w, {{ featured_image | img_url: '800x800' }} 800w, {{ featured_image | img_url: '1200x1200' }} 1200w" sizes="(max-width: 768px) 100vw, 50vw" alt="{{ featured_image.alt | default: product.title }}" width="800" height="800" /> </div> {% endif %} <!-- 其他图片(懒加载) --> {% for image in product.images offset: 1 %} <div class="gallery-image"> <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 800'%3E%3C/svg%3E" data-src="{{ image | img_url: '800x800' }}" data-srcset="{{ image | img_url: '400x400' }} 400w, {{ image | img_url: '600x600' }} 600w, {{ image | img_url: '800x800' }} 800w, {{ image | img_url: '1200x1200' }} 1200w" data-sizes="(max-width: 768px) 100vw, 50vw" alt="{{ image.alt | default: product.title }}" class="lazyload" width="800" height="800" /> </div> {% endfor %} </div>

数据预加载

<!-- 产品数据预加载 --> <script> // 预加载产品数据 window.productData = { id: {{ product.id }}, handle: '{{ product.handle }}', title: '{{ product.title | escape }}', vendor: '{{ product.vendor | escape }}', type: '{{ product.type | escape }}', available: {{ product.available | json }}, price: {{ product.price }}, compare_at_price: {% if product.compare_at_price %}{{ product.compare_at_price }}{% else %}null{% endif %}, price_varies: {{ product.price_varies | json }}, variants: {{ product.variants | json }}, images: [ {% for image in product.images %} { id: {{ image.id }}, url: '{{ image | img_url: '800x800' }}', alt: '{{ image.alt | escape }}' }{% unless forloop.last %},{% endunless %} {% endfor %} ], options: {{ product.options | json }}, tags: {{ product.tags | json }} } </script>

调试和测试

产品数据调试

<!-- 产品调试信息 --> {% if request.design_mode %} <div class="product-debug" style="margin-top: 2rem; padding: 1rem; background: #f5f5f5; font-family: monospace; font-size: 12px;"> <h4>产品调试信息</h4> <div><strong>基本信息:</strong></div> <ul> <li>ID: {{ product.id }}</li> <li>Handle: {{ product.handle }}</li> <li>Title: {{ product.title }}</li> <li>Vendor: {{ product.vendor }}</li> <li>Type: {{ product.type }}</li> <li>Available: {{ product.available }}</li> <li>Created: {{ product.created_at | date: '%Y-%m-%d %H:%M' }}</li> <li>Updated: {{ product.updated_at | date: '%Y-%m-%d %H:%M' }}</li> </ul> <div><strong>价格信息:</strong></div> <ul> <li>Price: {{ product.price | money }}</li> <li>Compare at price: {{ product.compare_at_price | money }}</li> <li>Price varies: {{ product.price_varies }}</li> <li>Price min: {{ product.price_min | money }}</li> <li>Price max: {{ product.price_max | money }}</li> </ul> <div><strong>变体信息:</strong></div> <ul> <li>Variants count: {{ product.variants.size }}</li> <li>Has only default variant: {{ product.has_only_default_variant }}</li> <li>Options: {{ product.options | join: ', ' }}</li> </ul> <div><strong>媒体信息:</strong></div> <ul> <li>Images count: {{ product.images.size }}</li> <li>Featured image: {% if product.featured_image %}{{ product.featured_image.alt }}{% else %}None{% endif %}</li> </ul> <div><strong>分类信息:</strong></div> <ul> <li>Collections: {{ product.collections | map: 'title' | join: ', ' }}</li> <li>Tags: {{ product.tags | join: ', ' }}</li> </ul> </div> {% endif %}

下一步学习

现在您已经掌握了产品对象的详细使用,建议继续学习:

最后更新时间: