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

购物车对象详解

购物车对象包含了用户当前购物车中的所有商品信息、价格计算、运费、税费等。掌握购物车对象是构建完整电商体验的关键。

购物车基本信息

购物车状态

<!-- 购物车基本信息 --> <div class="cart-summary" data-cart-count="{{ cart.item_count }}"> {% if cart.item_count > 0 %} <h2>购物车 ({{ cart.item_count }} 件商品)</h2> <div class="cart-meta"> <p><strong>商品数量:</strong> {{ cart.item_count }}</p> <p><strong>商品小计:</strong> {{ cart.items_subtotal_price | money }}</p> <p><strong>总价:</strong> {{ cart.total_price | money }}</p> {% if cart.total_discount > 0 %} <p class="discount"><strong>优惠:</strong> -{{ cart.total_discount | money }}</p> {% endif %} </div> {% else %} <div class="empty-cart"> <h2>购物车为空</h2> <p>您的购物车中还没有商品</p> <a href="{{ routes.all_products_collection_url }}" class="btn btn-primary">开始购物</a> </div> {% endif %} </div>

购物车商品

商品列表

<!-- 购物车商品列表 --> {% if cart.item_count > 0 %} <div class="cart-items"> {% for item in cart.items %} <div class="cart-item" data-variant-id="{{ item.variant.id }}"> <div class="item-image"> <img src="{{ item.image | img_url: '150x150' }}" alt="{{ item.product.title }}" loading="lazy" /> </div> <div class="item-details"> <h3 class="item-title"> <a href="{{ item.product.url }}">{{ item.product.title }}</a> </h3> {% unless item.variant.title == 'Default Title' %} <p class="item-variant">{{ item.variant.title }}</p> {% endunless %} {% if item.vendor != blank %} <p class="item-vendor">品牌: {{ item.vendor }}</p> {% endif %} {% if item.sku != blank %} <p class="item-sku">SKU: {{ item.sku }}</p> {% endif %} </div> <div class="item-price"> <div class="price-per-item"> {% if item.original_price != item.final_price %} <span class="original-price"><s>{{ item.original_price | money }}</s></span> <span class="final-price">{{ item.final_price | money }}</span> {% else %} <span class="price">{{ item.price | money }}</span> {% endif %} </div> </div> <div class="item-quantity"> <form action="{{ routes.cart_change_url }}" method="post" class="quantity-form"> <div class="quantity-controls"> <button type="button" class="quantity-decrease" onclick="updateQuantity({{ item.key }}, {{ item.quantity | minus: 1 }})">-</button> <input type="number" name="quantity" value="{{ item.quantity }}" min="0" class="quantity-input" onchange="updateQuantity({{ item.key }}, this.value)"> <button type="button" class="quantity-increase" onclick="updateQuantity({{ item.key }}, {{ item.quantity | plus: 1 }})">+</button> </div> </form> </div> <div class="item-total"> <span class="line-price">{{ item.final_line_price | money }}</span> </div> <div class="item-actions"> <button type="button" class="remove-item" onclick="removeItem({{ item.key }})"> 删除 </button> </div> </div> {% endfor %} </div> {% endif %}

购物车计算

价格摘要

<!-- 购物车价格摘要 --> <div class="cart-totals"> <table class="totals-table"> <tr> <td>商品小计:</td> <td>{{ cart.items_subtotal_price | money }}</td> </tr> {% if cart.cart_level_discount_applications.size > 0 %} {% for discount in cart.cart_level_discount_applications %} <tr class="discount"> <td>优惠 ({{ discount.title }}):</td> <td>-{{ discount.total_allocated_amount | money }}</td> </tr> {% endfor %} {% endif %} {% comment %} 运费计算需要在结账页面 {% endcomment %} <tr class="shipping-note"> <td colspan="2"> <small>运费将在结账时计算</small> </td> </tr> <tr class="total"> <td><strong>小计:</strong></td> <td><strong>{{ cart.total_price | money }}</strong></td> </tr> </table> </div>

购物车操作

添加商品

<!-- 添加商品到购物车 --> <form action="{{ routes.cart_add_url }}" method="post" class="product-form"> <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}"> <div class="quantity-selector"> <label for="quantity">数量:</label> <input type="number" id="quantity" name="quantity" value="1" min="1"> </div> <button type="submit" class="btn btn-primary add-to-cart"> 加入购物车 </button> </form> <script> // Ajax 添加商品 document.querySelector('.product-form').addEventListener('submit', function(e) { e.preventDefault() const formData = new FormData(this) fetch('/cart/add.js', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { // 更新购物车UI updateCartDrawer() showAddToCartNotification(data) }) .catch(error => { console.error('添加失败:', error) }) }) </script>

更新数量

<script> function updateQuantity(key, quantity) { fetch('/cart/change.js', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id: key, quantity: quantity }) }) .then(response => response.json()) .then(cart => { // 重新加载购物车页面或更新UI location.reload() }) } function removeItem(key) { updateQuantity(key, 0) } </script>

购物车抽屉

侧边栏购物车

<!-- 购物车抽屉 --> <div id="cart-drawer" class="cart-drawer"> <div class="cart-drawer-header"> <h3>购物车 (<span id="cart-count">{{ cart.item_count }}</span>)</h3> <button type="button" class="close-drawer">&times;</button> </div> <div class="cart-drawer-body"> {% if cart.item_count > 0 %} <div class="cart-items-mini"> {% for item in cart.items %} <div class="mini-cart-item"> <img src="{{ item.image | img_url: '80x80' }}" alt="{{ item.title }}"> <div class="item-info"> <h4>{{ item.product.title }}</h4> <p>{{ item.quantity }} × {{ item.final_price | money }}</p> </div> <button onclick="removeItem({{ item.key }})" class="remove-mini">×</button> </div> {% endfor %} </div> <div class="cart-drawer-footer"> <div class="cart-total"> <strong>总计: {{ cart.total_price | money }}</strong> </div> <div class="cart-actions"> <a href="{{ routes.cart_url }}" class="btn btn-outline">查看购物车</a> <a href="/checkout" class="btn btn-primary">立即结账</a> </div> </div> {% else %} <div class="empty-cart-drawer"> <p>购物车为空</p> </div> {% endif %} </div> </div>

优惠券和折扣

优惠码输入

<!-- 优惠码表单 --> <div class="discount-form"> <h4>优惠码</h4> <form action="{{ routes.cart_url }}" method="post" class="coupon-form"> <div class="input-group"> <input type="text" name="discount" placeholder="输入优惠码" value="{{ cart.discount.code }}" class="discount-input"> <button type="submit" class="btn btn-outline">应用</button> </div> </form> {% if cart.discount %} <div class="applied-discount"> <span>已应用: {{ cart.discount.code }}</span> <span class="discount-amount">-{{ cart.discount.amount | money }}</span> <a href="{{ routes.cart_url }}?discount=" class="remove-discount">移除</a> </div> {% endif %} </div>

结账流程

结账按钮

<!-- 结账区域 --> <div class="checkout-section"> {% if cart.item_count > 0 %} <div class="checkout-total"> <h3>订单总计: {{ cart.total_price | money }}</h3> </div> <div class="checkout-buttons"> <button type="submit" name="add" class="btn btn-primary btn-full checkout-btn" onclick="proceedToCheckout()"> 立即结账 </button> <!-- PayPal 快速结账 --> {% if shop.paypal_express_checkout %} <div class="paypal-express"> <button class="paypal-button">PayPal 快速支付</button> </div> {% endif %} <!-- Apple Pay / Google Pay --> <div class="digital-wallets"> <button class="apple-pay-button" style="display: none;">Apple Pay</button> <button class="google-pay-button" style="display: none;">Google Pay</button> </div> </div> <div class="checkout-notes"> <label for="cart-note">订单备注:</label> <textarea id="cart-note" name="note" placeholder="特殊要求或备注信息" onchange="updateCartNote(this.value)">{{ cart.note }}</textarea> </div> {% endif %} </div> <script> function proceedToCheckout() { window.location.href = '/checkout' } function updateCartNote(note) { fetch('/cart/update.js', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ note: note }) }) } </script>

购物车持久化

本地存储

<script> // 购物车状态管理 const CartManager = { // 获取购物车数据 getCart: function() { return fetch('/cart.js') .then(response => response.json()) }, // 添加商品 addItem: function(variantId, quantity = 1, properties = {}) { return fetch('/cart/add.js', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id: variantId, quantity: quantity, properties: properties }) }).then(response => response.json()) }, // 更新商品数量 updateItem: function(key, quantity) { return fetch('/cart/change.js', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id: key, quantity: quantity }) }).then(response => response.json()) }, // 清空购物车 clearCart: function() { return fetch('/cart/clear.js', { method: 'POST' }).then(response => response.json()) }, // 更新购物车UI updateCartUI: function(cart) { document.getElementById('cart-count').textContent = cart.item_count // 更新其他UI元素 } } // 页面加载时初始化购物车 document.addEventListener('DOMContentLoaded', function() { CartManager.getCart().then(cart => { CartManager.updateCartUI(cart) }) }) </script>

性能优化

Ajax 购物车

<!-- 购物车数据预加载 --> <script> window.cartData = {{ cart | json }}; // 异步更新购物车 function refreshCart() { return fetch('/cart.js') .then(response => response.json()) .then(cart => { window.cartData = cart updateCartDisplay(cart) return cart }) } function updateCartDisplay(cart) { // 更新购物车计数 document.querySelectorAll('.cart-count').forEach(el => { el.textContent = cart.item_count }) // 更新总价显示 document.querySelectorAll('.cart-total').forEach(el => { el.textContent = formatMoney(cart.total_price) }) } function formatMoney(cents) { return '¥' + (cents / 100).toFixed(2) } </script>

调试工具

购物车调试

<!-- 购物车调试信息 --> {% if request.design_mode %} <div class="cart-debug" style="margin-top: 2rem; padding: 1rem; background: #fff3cd; font-family: monospace; font-size: 12px;"> <h4>购物车调试信息</h4> <div><strong>基本信息:</strong></div> <ul> <li>商品数量: {{ cart.item_count }}</li> <li>商品小计: {{ cart.items_subtotal_price | money }}</li> <li>总价: {{ cart.total_price | money }}</li> <li>折扣金额: {{ cart.total_discount | money }}</li> <li>总重量: {{ cart.total_weight }}g</li> </ul> <div><strong>商品列表:</strong></div> {% for item in cart.items %} <div style="margin: 10px 0; padding: 10px; border: 1px solid #ddd;"> <strong>{{ item.product.title }}</strong><br> 变体: {{ item.variant.title }}<br> 数量: {{ item.quantity }}<br> 单价: {{ item.price | money }}<br> 小计: {{ item.line_price | money }}<br> Key: {{ item.key }} </div> {% endfor %} </div> {% endif %}

下一步学习

现在您已经掌握了购物车对象的使用,建议继续学习:

最后更新时间: