变量和对象
在 Liquid 模板中,变量和对象是处理动态内容的核心。本指南将详细介绍如何创建、使用和操作变量与对象。
变量基础
变量声明
<!-- 基本变量赋值 -->
{% assign product_title = product.title %}
{% assign sale_price = product.price | times: 0.8 %}
{% assign is_featured = true %}
<!-- 字符串变量 -->
{% assign welcome_message = "欢迎来到我们的商店!" %}
{% assign css_class = "product-card featured" %}
<!-- 数字变量 -->
{% assign max_items = 10 %}
{% assign discount_rate = 0.15 %}
<!-- 使用变量 -->
<h1>{{ product_title }}</h1>
<p class="{{ css_class }}">特价: {{ sale_price | money }}</p>
变量命名规则
<!-- 好的变量命名 -->
{% assign product_count = collection.products.size %}
{% assign user_is_logged_in = customer != null %}
{% assign featured_products = collection.products | where: 'featured', true %}
<!-- 避免的命名方式 -->
{% assign pc = collection.products.size %}
{% assign x = customer != null %}
{% assign fp = collection.products | where: 'featured', true %}
变量作用域
<!-- 全局变量 (在当前模板中可用) -->
{% assign global_var = "全局变量" %}
<!-- 循环中的局部变量 -->
{% for product in collection.products %}
{% assign loop_var = "循环变量" %}
<!-- loop_var 只在此循环中可用 -->
{{ loop_var }}
{% endfor %}
<!-- 条件中的变量 -->
{% if customer %}
{% assign customer_name = customer.first_name %}
<!-- customer_name 在条件块外也可用 -->
{% endif %}
{{ customer_name }} <!-- 如果条件成立,这里可以访问 -->
捕获变量
基本捕获
<!-- 捕获简单内容 -->
{% capture greeting %}
Hello, {{ customer.first_name | default: "Guest" }}!
{% endcapture %}
<h1>{{ greeting }}</h1>
<!-- 捕获 HTML 内容 -->
{% capture product_badge %}
{% if product.compare_at_price > product.price %}
<span class="sale-badge">促销</span>
{% elsif product.tags contains 'new' %}
<span class="new-badge">新品</span>
{% elsif product.tags contains 'featured' %}
<span class="featured-badge">推荐</span>
{% endif %}
{% endcapture %}
<div class="product-info">
{{ product_badge }}
<h3>{{ product.title }}</h3>
</div>
复杂捕获示例
<!-- 捕获产品信息卡片 -->
{% capture product_info_card %}
<div class="product-info-card">
<h3>{{ product.title }}</h3>
<!-- 价格信息 -->
<div class="price-info">
{% if product.compare_at_price > product.price %}
{% assign savings = product.compare_at_price | minus: product.price %}
{% assign savings_percent = savings | times: 100 | divided_by: product.compare_at_price | round %}
<span class="original-price">{{ product.compare_at_price | money }}</span>
<span class="sale-price">{{ product.price | money }}</span>
<span class="savings">节省 {{ savings_percent }}%</span>
{% else %}
<span class="regular-price">{{ product.price | money }}</span>
{% endif %}
</div>
<!-- 库存状态 -->
{% if product.available %}
<span class="stock-status available">有库存</span>
{% else %}
<span class="stock-status unavailable">缺货</span>
{% endif %}
<!-- 评分显示 -->
{% if product.metafields.reviews.rating %}
<div class="rating">
{% assign rating = product.metafields.reviews.rating | round %}
{% for i in (1..5) %}
{% if i <= rating %}
<span class="star filled">★</span>
{% else %}
<span class="star empty">☆</span>
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% endcapture %}
<!-- 使用捕获的内容 -->
{{ product_info_card }}
条件捕获
<!-- 根据条件捕获不同内容 -->
{% capture shipping_info %}
{% if cart.total_weight > 5000 %}
<p class="shipping-notice heavy">
大件商品,预计3-5个工作日送达
</p>
{% elsif cart.total_price > 50000 %}
<p class="shipping-notice free">
免费包邮!1-2个工作日送达
</p>
{% else %}
<p class="shipping-notice standard">
标准配送,2-3个工作日送达,运费 {{ 800 | money }}
</p>
{% endif %}
{% endcapture %}
<div class="cart-summary">
{{ shipping_info }}
</div>
对象访问
基本对象访问
<!-- 点号访问 -->
{{ product.title }}
{{ customer.first_name }}
{{ shop.name }}
<!-- 方括号访问 -->
{{ product['title'] }}
{{ customer['first_name'] }}
{{ shop['name'] }}
<!-- 动态属性访问 -->
{% assign property_name = 'title' %}
{{ product[property_name] }}
嵌套对象访问
<!-- 深层嵌套访问 -->
{{ product.selected_or_first_available_variant.title }}
{{ customer.default_address.city }}
{{ order.line_items.first.product.title }}
<!-- 安全访问 (避免错误) -->
{% if product.featured_image %}
{{ product.featured_image.alt }}
{% endif %}
<!-- 使用 default 过滤器 -->
{{ product.featured_image.alt | default: product.title }}
数组对象访问
<!-- 数组索引访问 -->
{{ product.images[0] }}
{{ collection.products[5] }}
{{ customer.addresses[1] }}
<!-- 数组方法 -->
{{ product.images.first }}
{{ product.images.last }}
{{ collection.products.size }}
<!-- 遍历数组 -->
{% for image in product.images %}
<img src="{{ image | img_url: '300x300' }}"
alt="{{ image.alt | escape }}">
{% endfor %}
对象属性检查
检查属性是否存在
<!-- 检查对象是否存在 -->
{% if customer %}
<p>欢迎回来,{{ customer.first_name }}!</p>
{% else %}
<p>请登录您的账户</p>
{% endif %}
<!-- 检查属性是否存在 -->
{% if product.description %}
<div class="product-description">
{{ product.description }}
</div>
{% endif %}
<!-- 检查属性是否为空 -->
{% if product.description != blank %}
<div class="product-description">
{{ product.description }}
</div>
{% endif %}
属性存在性的复杂检查
<!-- 检查图片是否存在 -->
{% if product.featured_image %}
<div class="product-image">
<img src="{{ product.featured_image | img_url: '400x400' }}"
alt="{{ product.featured_image.alt | escape | default: product.title }}">
</div>
{% else %}
<div class="no-image">
<span>暂无图片</span>
</div>
{% endif %}
<!-- 检查变体选项 -->
{% if product.variants.size > 1 %}
<div class="variant-selector">
<select name="id">
{% for variant in product.variants %}
<option value="{{ variant.id }}"
{% if variant.available %}{% else %}disabled{% endif %}>
{{ variant.title }}
{% unless variant.available %} - 缺货{% endunless %}
</option>
{% endfor %}
</select>
</div>
{% else %}
<input type="hidden" name="id" value="{{ product.first_available_variant.id }}">
{% endif %}
动态变量创建
使用循环创建变量
<!-- 为每个产品类型创建计数器 -->
{% assign electronics_count = 0 %}
{% assign clothing_count = 0 %}
{% assign books_count = 0 %}
{% for product in collection.products %}
{% case product.type %}
{% when 'Electronics' %}
{% assign electronics_count = electronics_count | plus: 1 %}
{% when 'Clothing' %}
{% assign clothing_count = clothing_count | plus: 1 %}
{% when 'Books' %}
{% assign books_count = books_count | plus: 1 %}
{% endcase %}
{% endfor %}
<div class="category-stats">
<p>电子产品: {{ electronics_count }}</p>
<p>服装类: {{ clothing_count }}</p>
<p>图书类: {{ books_count }}</p>
</div>
动态CSS类创建
<!-- 根据产品状态创建CSS类 -->
{% assign product_classes = "product-card" %}
{% if product.available %}
{% assign product_classes = product_classes | append: " available" %}
{% else %}
{% assign product_classes = product_classes | append: " out-of-stock" %}
{% endif %}
{% if product.compare_at_price > product.price %}
{% assign product_classes = product_classes | append: " on-sale" %}
{% endif %}
{% if product.tags contains "featured" %}
{% assign product_classes = product_classes | append: " featured" %}
{% endif %}
{% if product.tags contains "new" %}
{% assign product_classes = product_classes | append: " new" %}
{% endif %}
<div class="{{ product_classes }}">
<!-- 产品内容 -->
</div>
数据转换和处理
字符串处理
<!-- 字符串清理和格式化 -->
{% assign clean_title = product.title | strip | downcase %}
{% assign url_slug = product.title | handleize %}
{% assign search_terms = product.title | split: ' ' | join: '+' %}
<!-- 创建面包屑导航 -->
{% assign breadcrumb_items = "" %}
{% assign breadcrumb_items = breadcrumb_items | append: '<a href="/">首页</a>' %}
{% assign breadcrumb_items = breadcrumb_items | append: ' > ' %}
{% assign breadcrumb_items = breadcrumb_items | append: '<a href="/collections">所有产品</a>' %}
{% assign breadcrumb_items = breadcrumb_items | append: ' > ' %}
{% assign breadcrumb_items = breadcrumb_items | append: '<a href="' | append: collection.url | append: '">' | append: collection.title | append: '</a>' %}
{% assign breadcrumb_items = breadcrumb_items | append: ' > ' %}
{% assign breadcrumb_items = breadcrumb_items | append: product.title %}
<nav class="breadcrumb">
{{ breadcrumb_items }}
</nav>
数字计算
<!-- 复杂价格计算 -->
{% assign base_price = product.price %}
{% assign tax_rate = 0.08 %}
{% assign shipping_cost = 800 %}
{% assign subtotal = base_price %}
{% assign tax_amount = subtotal | times: tax_rate %}
{% assign total_before_shipping = subtotal | plus: tax_amount %}
{% assign final_total = total_before_shipping | plus: shipping_cost %}
<!-- 折扣计算 -->
{% if product.compare_at_price > product.price %}
{% assign discount_amount = product.compare_at_price | minus: product.price %}
{% assign discount_percent = discount_amount | times: 100.0 | divided_by: product.compare_at_price | round: 1 %}
{% endif %}
<div class="price-breakdown">
<div class="line-item">
<span>商品价格:</span>
<span>{{ subtotal | money }}</span>
</div>
<div class="line-item">
<span>税费 ({{ tax_rate | times: 100 }}%):</span>
<span>{{ tax_amount | money }}</span>
</div>
<div class="line-item">
<span>运费:</span>
<span>{{ shipping_cost | money }}</span>
</div>
<div class="line-item total">
<span>总计:</span>
<span>{{ final_total | money }}</span>
</div>
{% if discount_percent %}
<div class="savings">
您节省了 {{ discount_percent }}% ({{ discount_amount | money }})
</div>
{% endif %}
</div>
数组操作
<!-- 产品标签处理 -->
{% assign all_tags = "" %}
{% for product in collection.products %}
{% for tag in product.tags %}
{% unless all_tags contains tag %}
{% if all_tags == "" %}
{% assign all_tags = tag %}
{% else %}
{% assign all_tags = all_tags | append: "," | append: tag %}
{% endif %}
{% endunless %}
{% endfor %}
{% endfor %}
{% assign unique_tags = all_tags | split: "," | sort %}
<!-- 显示标签过滤器 -->
<div class="tag-filters">
<h3>按标签筛选:</h3>
{% for tag in unique_tags %}
<a href="{{ collection.url }}/{{ tag | handleize }}"
class="tag-filter">{{ tag }}</a>
{% endfor %}
</div>
条件变量赋值
三元操作模拟
<!-- 模拟三元操作符 -->
{% if product.available %}
{% assign stock_status = "有库存" %}
{% assign stock_class = "in-stock" %}
{% else %}
{% assign stock_status = "缺货" %}
{% assign stock_class = "out-of-stock" %}
{% endif %}
<span class="{{ stock_class }}">{{ stock_status }}</span>
<!-- 使用 default 过滤器简化 -->
{% assign display_price = product.price | default: "价格面议" %}
{% assign product_image = product.featured_image | default: "默认图片" %}
复杂条件赋值
<!-- 根据多个条件设置变量 -->
{% assign product_priority = 0 %}
{% if product.tags contains "bestseller" %}
{% assign product_priority = product_priority | plus: 10 %}
{% endif %}
{% if product.tags contains "featured" %}
{% assign product_priority = product_priority | plus: 5 %}
{% endif %}
{% if product.created_at > "2023-01-01" %}
{% assign product_priority = product_priority | plus: 3 %}
{% endif %}
{% if product.variants.size > 1 %}
{% assign product_priority = product_priority | plus: 2 %}
{% endif %}
<!-- 根据优先级确定显示样式 -->
{% if product_priority >= 15 %}
{% assign priority_class = "highest-priority" %}
{% elsif product_priority >= 10 %}
{% assign priority_class = "high-priority" %}
{% elsif product_priority >= 5 %}
{% assign priority_class = "medium-priority" %}
{% else %}
{% assign priority_class = "normal-priority" %}
{% endif %}
<div class="product-card {{ priority_class }}">
<!-- 产品内容 -->
</div>
变量调试
输出变量信息
<!-- 调试变量内容 -->
{% if settings.debug_mode %}
<div class="debug-info">
<h4>调试信息</h4>
<pre>{{ product | json }}</pre>
<p>产品ID: {{ product.id }}</p>
<p>产品类型: {{ product.type }}</p>
<p>变体数量: {{ product.variants.size }}</p>
<p>标签: {{ product.tags | join: ", " }}</p>
<!-- 检查变量存在性 -->
<p>描述存在: {{ product.description != blank }}</p>
<p>图片存在: {{ product.featured_image != blank }}</p>
<p>评论存在: {{ product.metafields.reviews != blank }}</p>
</div>
{% endif %}
性能监控变量
<!-- 跟踪处理时间 -->
{% assign start_time = 'now' | date: '%s' %}
<!-- 复杂处理逻辑 -->
{% assign processed_products = collection.products | where: 'available', true | sort: 'price' %}
{% assign end_time = 'now' | date: '%s' %}
{% assign processing_time = end_time | minus: start_time %}
{% if settings.debug_mode %}
<p>处理了 {{ processed_products.size }} 个产品,耗时 {{ processing_time }} 秒</p>
{% endif %}
最佳实践
1. 变量命名
<!-- 好的命名 -->
{% assign featured_products = collection.products | where: 'featured', true %}
{% assign customer_is_logged_in = customer != blank %}
{% assign cart_item_count = cart.item_count %}
<!-- 避免的命名 -->
{% assign fp = collection.products | where: 'featured', true %}
{% assign c = customer != blank %}
{% assign count = cart.item_count %}
2. 性能优化
<!-- 避免重复计算 -->
{% assign sale_products = collection.products | where: 'compare_at_price_min', '>', 0 %}
{% for product in sale_products %}
<!-- 使用预筛选的产品 -->
{% endfor %}
<!-- 缓存复杂计算 -->
{% assign complex_calculation = product.price | times: 0.85 | plus: 500 | money %}
<span class="special-price">{{ complex_calculation }}</span>
<span class="note">特价: {{ complex_calculation }}</span>
3. 错误处理
<!-- 安全的对象访问 -->
{% if product.featured_image %}
{% assign image_alt = product.featured_image.alt | default: product.title %}
{% else %}
{% assign image_alt = product.title %}
{% endif %}
<!-- 处理空值 -->
{% assign description = product.description | default: "暂无描述" %}
{% assign vendor = product.vendor | default: "未知品牌" %}
下一步学习
掌握变量和对象操作后,建议继续学习:
- 数据类型详解 - 深入了解各种数据类型
- 过滤器完全指南 - 学习数据处理技巧
- 标签和控制结构 - 掌握流程控制
- Shopify 对象参考 - 了解特定对象
熟练掌握变量和对象操作是创建动态、灵活的 Shopify 主题的基础!
最后更新时间: