Skip to Content
🎉 探索 Shopify 的无限可能 结构化知识 + 实战案例,持续更新中...
Liquid 开发Liquid 最佳实践

Liquid 最佳实践

本指南汇总了 Shopify Liquid 开发中的最佳实践,帮助您编写高质量、高性能、可维护的代码。

代码组织和结构

1. 清晰的文件组织

<!-- 按功能组织 snippets --> snippets/ ├── product/ │ ├── product-card.liquid │ ├── product-gallery.liquid │ ├── product-form.liquid │ └── product-reviews.liquid ├── cart/ │ ├── cart-drawer.liquid │ ├── cart-item.liquid │ └── cart-summary.liquid ├── navigation/ │ ├── main-menu.liquid │ ├── breadcrumbs.liquid │ └── pagination.liquid └── utilities/ ├── image-responsive.liquid ├── price-display.liquid └── social-sharing.liquid

2. 一致的命名约定

<!-- 好的命名约定 --> {% assign product_is_available = product.available %} {% assign customer_is_vip = customer.tags contains 'vip' %} {% assign cart_has_items = cart.item_count > 0 %} {% assign collection_is_empty = collection.products.size == 0 %} <!-- 避免的命名方式 --> {% assign pa = product.available %} {% assign c_vip = customer.tags contains 'vip' %} {% assign cart_items = cart.item_count > 0 %} {% assign empty = collection.products.size == 0 %}

3. 逻辑分层

<!-- 数据准备层 --> {% comment %} === 数据收集和预处理 === {% endcomment %} {% assign featured_products = collection.products | where: 'tags', 'featured' %} {% assign sale_products = collection.products | where: 'compare_at_price_max', '>', 0 %} {% assign product_count = collection.products.size %} {% comment %} === 用户状态检查 === {% endcomment %} {% assign customer_is_logged_in = customer != null %} {% assign customer_is_vip = customer.tags contains 'vip' %} {% assign is_mobile_device = request.user_agent contains 'Mobile' %} {% comment %} === 业务逻辑层 === {% endcomment %} {% if customer_is_vip and featured_products.size > 0 %} {% assign display_products = featured_products %} {% assign section_title = "VIP 专享精选" %} {% elsif sale_products.size > 0 %} {% assign display_products = sale_products %} {% assign section_title = "限时特价" %} {% else %} {% assign display_products = collection.products %} {% assign section_title = collection.title %} {% endif %} {% comment %} === 显示层 === {% endcomment %} <section class="products-section"> <h2>{{ section_title }}</h2> <div class="products-grid"> {% for product in display_products limit: 12 %} {% render 'product-card', product: product, context: 'collection' %} {% endfor %} </div> </section>

性能最佳实践

1. 避免重复计算

<!-- 不好的做法 --> {% for product in collection.products %} {% if collection.products.size > 10 %} <!-- size 在每次循环中都被计算 --> {% endif %} {% if collection.products | where: 'available', true | size > 5 %} <!-- 复杂过滤在每次循环中都被执行 --> {% endif %} {% endfor %} <!-- 好的做法 --> {% assign total_products = collection.products.size %} {% assign available_products = collection.products | where: 'available', true %} {% assign available_count = available_products.size %} {% for product in collection.products %} {% if total_products > 10 %} <!-- 使用预计算的值 --> {% endif %} {% if available_count > 5 %} <!-- 使用预计算的值 --> {% endif %} {% endfor %}

2. 高效的对象访问

<!-- 缓存深层对象访问 --> {% assign selected_variant = product.selected_or_first_available_variant %} {% assign featured_image = product.featured_image %} {% assign customer_address = customer.default_address %} <!-- 使用缓存的值 --> {% if selected_variant.available %} <p>价格: {{ selected_variant.price | money }}</p> <p>库存: {{ selected_variant.inventory_quantity }}</p> {% endif %} {% if featured_image %} <img src="{{ featured_image | img_url: '400x400' }}" alt="{{ featured_image.alt | default: product.title }}"> {% endif %}

3. 智能过滤和排序

<!-- 链式过滤优化 --> {% assign featured_available_products = collection.products | where: 'available', true | where: 'tags', 'featured' | sort: 'created_at' | reverse %} <!-- 条件性过滤 --> {% if settings.show_only_available %} {% assign display_products = collection.products | where: 'available', true %} {% else %} {% assign display_products = collection.products %} {% endif %} {% if settings.sort_by_price %} {% assign display_products = display_products | sort: 'price' %} {% elsif settings.sort_by_date %} {% assign display_products = display_products | sort: 'created_at' | reverse %} {% endif %}

4. 循环优化

<!-- 使用 limit 避免处理过多数据 --> {% for product in collection.products limit: 20 %} {% render 'product-card', product: product %} {% endfor %} <!-- 早期跳出和继续 --> {% for product in collection.products %} {% unless product.available %} {% continue %} {% endunless %} {% if forloop.index > 12 %} {% break %} {% endif %} {% render 'product-card', product: product %} {% endfor %} <!-- 条件性循环 --> {% if collection.products.size > 0 %} {% for product in collection.products %} {% render 'product-card', product: product %} {% endfor %} {% else %} {% render 'empty-collection' %} {% endif %}

安全性最佳实践

1. 输出转义

<!-- 总是转义用户输入和不信任的内容 --> <h1>{{ product.title | escape }}</h1> <p>{{ product.description | escape }}</p> <meta name="description" content="{{ product.description | strip_html | escape }}"> <!-- URL 安全 --> <a href="{{ product.url | escape }}">{{ product.title | escape }}</a> <!-- 属性值转义 --> <img src="{{ product.featured_image | img_url: '400x400' }}" alt="{{ product.featured_image.alt | escape | default: product.title | escape }}"> <!-- JavaScript 上下文中的转义 --> <script> var productTitle = {{ product.title | json }}; var productData = {{ product | json }}; </script>

2. 安全的动态内容

<!-- 验证和清理用户输入 --> {% assign search_query = request.params.q | strip | escape %} {% if search_query.size > 0 and search_query.size <= 100 %} <p>搜索: "{{ search_query }}"</p> {% endif %} <!-- 安全的 URL 构建 --> {% assign safe_handle = product.handle | escape %} <a href="/products/{{ safe_handle }}">{{ product.title | escape }}</a> <!-- 验证对象存在性 --> {% if customer and customer.email %} <p>欢迎, {{ customer.first_name | escape }}!</p> {% endif %}

3. 防止 XSS 攻击

<!-- 在 HTML 属性中使用内容 --> <div data-product-id="{{ product.id }}" data-product-title="{{ product.title | escape }}" data-product-price="{{ product.price }}"> </div> <!-- 在 CSS 中使用内容 --> <style> .product-{{ product.id }} { /* 只使用已知安全的值 */ background-color: {{ settings.product_bg_color }}; } </style> <!-- 避免在 JavaScript 中直接输出 --> <!-- 不好的做法 --> <script> var title = "{{ product.title }}"; // 可能被注入 </script> <!-- 好的做法 --> <script> var title = {{ product.title | json }}; // 安全的 JSON 序列化 </script>

错误处理和容错性

1. 防御性编程

<!-- 检查对象存在性 --> {% if product and product.featured_image %} <img src="{{ product.featured_image | img_url: '400x400' }}" alt="{{ product.featured_image.alt | default: product.title }}"> {% else %} <div class="no-image-placeholder"> <span>暂无图片</span> </div> {% endif %} <!-- 提供默认值 --> {% assign product_title = product.title | default: "未命名商品" %} {% assign product_price = product.price | default: 0 %} {% assign product_description = product.description | default: "暂无描述" %} <!-- 安全的数组访问 --> {% if product.images.size > 0 %} {% assign first_image = product.images[0] %} {% assign gallery_images = product.images | offset: 1 %} {% endif %}

2. 回退机制

<!-- 集合回退 --> {% assign featured_collection = collections[settings.featured_collection_handle] %} {% assign display_collection = featured_collection | default: collections.all %} <!-- 图片回退 --> {% assign product_image = product.featured_image | default: 'placeholder.svg' %} <img src="{{ product_image | img_url: '400x400' }}" alt="{{ product.title }}"> <!-- 模板回退 --> {% if template == 'product.special' %} {% render 'product-special' %} {% elsif template == 'product.simple' %} {% render 'product-simple' %} {% else %} {% render 'product-default' %} {% endif %}

3. 错误状态处理

<!-- 空状态处理 --> {% if collection.products.size > 0 %} <div class="products-grid"> {% for product in collection.products %} {% render 'product-card', product: product %} {% endfor %} </div> {% else %} <div class="empty-collection"> <h3>暂无商品</h3> <p>该分类下还没有商品,请查看其他分类或稍后再来。</p> <a href="/collections" class="btn">浏览所有分类</a> </div> {% endif %} <!-- 加载状态 --> {% if search.performed %} {% if search.results.size > 0 %} <!-- 显示搜索结果 --> {% else %} <div class="no-results"> <h3>未找到相关结果</h3> <p>请尝试使用不同的关键词进行搜索。</p> </div> {% endif %} {% else %} <div class="search-prompt"> <h3>搜索我们的产品</h3> <p>输入关键词找到您需要的商品。</p> </div> {% endif %}

可维护性最佳实践

1. 模块化设计

<!-- 将复杂组件分解为小的可重用片段 --> <!-- snippets/product/product-card.liquid --> <div class="product-card" data-product-id="{{ product.id }}"> {% render 'product/product-image', product: product, size: size %} {% render 'product/product-info', product: product, show_vendor: show_vendor %} {% render 'product/product-actions', product: product, quick_shop: quick_shop %} </div> <!-- snippets/product/product-image.liquid --> {% assign image_size = size | default: '300x300' %} {% if product.featured_image %} <div class="product-image"> <img src="{{ product.featured_image | img_url: image_size }}" alt="{{ product.featured_image.alt | default: product.title }}" loading="lazy"> {% if product.images.size > 1 %} <div class="image-count">+{{ product.images.size | minus: 1 }}</div> {% endif %} </div> {% else %} <div class="product-image-placeholder"> <span>暂无图片</span> </div> {% endif %}

2. 配置驱动的开发

<!-- 使用设置来控制行为 --> {% assign show_vendor = show_vendor | default: settings.show_product_vendor %} {% assign show_reviews = show_reviews | default: settings.show_product_reviews %} {% assign card_style = card_style | default: settings.product_card_style %} <div class="product-card product-card--{{ card_style }}"> {% if show_vendor and product.vendor %} <p class="product-vendor">{{ product.vendor }}</p> {% endif %} <h3 class="product-title"> <a href="{{ product.url }}">{{ product.title }}</a> </h3> {% render 'price-display', product: product %} {% if show_reviews %} {% render 'product-reviews-summary', product: product %} {% endif %} </div>

3. 文档化代码

{% comment %} 产品卡片组件 参数: - product: 产品对象 (必需) - size: 图片尺寸,例如 '300x300' (可选,默认 '300x300') - show_vendor: 是否显示品牌 (可选,默认 false) - show_reviews: 是否显示评论 (可选,默认 false) - context: 使用上下文,例如 'collection', 'search' (可选) 使用示例: {% render 'product-card', product: product, size: '400x400', show_vendor: true, context: 'collection' %} {% endcomment %} {% assign image_size = size | default: '300x300' %} {% assign show_vendor = show_vendor | default: false %} {% assign show_reviews = show_reviews | default: false %} <div class="product-card" data-context="{{ context }}"> <!-- 组件内容 --> </div>

国际化和本地化

1. 多语言支持

<!-- 使用翻译键 --> <h2>{{ 'products.general.featured_title' | t }}</h2> <p>{{ 'products.general.showing_count' | t: count: collection.products.size }}</p> <!-- 带参数的翻译 --> {% assign remaining = 50000 | minus: cart.total_price %} <p>{{ 'cart.general.free_shipping_remaining' | t: amount: remaining | money }}</p> <!-- 复数形式处理 --> <span class="cart-count"> {{ 'cart.general.item_count' | t: count: cart.item_count }} </span> <!-- 日期本地化 --> <time datetime="{{ article.published_at | date: '%Y-%m-%d' }}"> {{ article.published_at | date: format: 'month_day_year' }} </time>

2. 货币和地区适配

<!-- 货币显示 --> <span class="price">{{ product.price | money }}</span> <span class="price-no-currency">{{ product.price | money_without_currency }}</span> <span class="price-with-currency">{{ product.price | money_with_currency }}</span> <!-- 地区特定格式 --> {% case shop.locale %} {% when 'zh-CN' %} <p>免费送货到中国大陆</p> {% when 'en-US' %} <p>Free shipping to United States</p> {% else %} <p>{{ 'shipping.free_shipping' | t }}</p> {% endcase %}

可访问性最佳实践

1. 语义化 HTML

<!-- 使用正确的 HTML 结构 --> <nav aria-label="主导航"> <ul> {% for link in linklists.main-menu.links %} <li> <a href="{{ link.url }}" {% if link.current %}aria-current="page"{% endif %}> {{ link.title }} </a> </li> {% endfor %} </ul> </nav> <!-- 表单标签 --> <form action="/search" method="get"> <label for="search-input">搜索产品</label> <input type="search" id="search-input" name="q" placeholder="输入关键词" value="{{ search.terms }}" aria-describedby="search-help"> <div id="search-help" class="sr-only"> 输入产品名称或关键词进行搜索 </div> <button type="submit">搜索</button> </form>

2. 图片无障碍

<!-- 提供有意义的替代文本 --> <img src="{{ product.featured_image | img_url: '400x400' }}" alt="{% if product.featured_image.alt %}{{ product.featured_image.alt }}{% else %}{{ product.title }}的产品图片{% endif %}" loading="lazy"> <!-- 装饰性图片 --> <img src="{{ 'decoration.svg' | asset_url }}" alt="" role="presentation"> <!-- 图片说明 --> <figure> <img src="{{ article.image | img_url: '800x400' }}" alt="{{ article.image.alt }}"> {% if article.image.alt %} <figcaption>{{ article.image.alt }}</figcaption> {% endif %} </figure>

3. 键盘导航和屏幕阅读器

<!-- 跳转链接 --> <a href="#main-content" class="skip-link">跳转到主要内容</a> <!-- 可访问的按钮 --> <button type="button" class="cart-toggle" aria-expanded="false" aria-controls="cart-drawer" aria-label="打开购物车,当前有 {{ cart.item_count }} 件商品"> 购物车 ({{ cart.item_count }}) </button> <!-- 状态通知 --> <div id="cart-status" class="sr-only" aria-live="polite" aria-atomic="true"> <!-- 动态更新购物车状态 --> </div>

测试和调试

1. 开发环境调试

<!-- 开发模式检查 --> {% assign is_development = request.host contains '.myshopify.com' %} {% if is_development or settings.debug_mode %} <div class="debug-info"> <h4>调试信息</h4> <ul> <li>模板: {{ template }}</li> <li>页面类型: {{ request.page_type }}</li> <li>用户代理: {{ request.user_agent | truncate: 50 }}</li> {% if product %} <li>产品ID: {{ product.id }}</li> <li>产品句柄: {{ product.handle }}</li> {% endif %} </ul> </div> {% endif %}

2. 性能监控

<!-- 简单的性能指标 --> {% if settings.show_performance_info %} <div class="performance-info"> <p>对象数量: {{ collection.products.size }}</p> <p>渲染时间: {{ 'now' | date: '%s' }}</p> </div> {% endif %}

部署和维护

1. 环境管理

<!-- 环境特定配置 --> {% case request.host %} {% when 'localhost' %} {% assign analytics_id = 'dev-123' %} {% assign debug_mode = true %} {% when 'staging.myshop.com' %} {% assign analytics_id = 'staging-456' %} {% assign debug_mode = true %} {% else %} {% assign analytics_id = settings.analytics_id %} {% assign debug_mode = false %} {% endcase %}

2. 版本控制友好的代码

<!-- 避免硬编码值 --> {% assign featured_limit = settings.featured_products_limit | default: 8 %} {% assign grid_columns = settings.products_per_row | default: 4 %} <!-- 使用版本化的资源 --> {{ 'theme.css' | asset_url | stylesheet_tag }} {{ 'app.js' | asset_url | script_tag }}

总结

遵循这些最佳实践将帮助您:

  1. 提高代码质量 - 编写更清晰、更可维护的代码
  2. 提升性能 - 减少不必要的计算和优化渲染
  3. 增强安全性 - 防止安全漏洞和数据泄露
  4. 改善用户体验 - 提供更好的可访问性和多语言支持
  5. 简化维护 - 通过模块化和文档化降低维护成本

下一步学习

掌握最佳实践后,建议继续学习:

  1. 性能优化 - 深入性能优化技巧
  2. 调试和故障排除 - 问题诊断和解决
  3. 主题开发实战 - 实际项目应用
  4. 代码组织和结构 - 高级组织模式

持续改进和遵循最佳实践是成为优秀 Liquid 开发者的关键!

最后更新时间: