网站已运行 163 · 12小时 · 27 · 33
目录

Shopify Liquid snippet 实作:render 参数、作用域与 LiquidDoc

花括号包围可复用代码模块的 Shopify Liquid snippet 特色封面

Shopify Liquid snippet 适合把价格、图标、卡片等重复输出拆成可复用的小文件,但真正容易出错的地方不是“把代码放进 snippets 目录”,而是参数怎么传、变量在哪个作用域可见,以及怎样让后续维护者知道它需要什么数据。本文用 Dawn 的真实调用方式和一个通过 Theme Check 的小示例,把这三件事串起来。

Shopify Liquid render 将 section 参数传入 snippet 并输出商品价格的关系示意图
render 把明确参数送进独立的 snippet 作用域,再由 snippet 输出结果。此图为关系示意,不是 Shopify 后台截图。

snippet 和 render 分别解决什么问题

snippet 是 snippets 目录中的 Liquid 文件。它不会像 section、block 那样直接出现在主题编辑器里,而是由其他 Liquid 文件调用。适合放进去的通常是“有清晰输入、产生一段输出、会在多个位置复用”的内容,例如价格、评分、图标或商品卡片的局部结构。

render 则负责执行 snippet,并通过命名参数把数据传进去。Shopify 官方文档明确说明,render 创建的是隔离作用域:调用位置自己创建的局部变量不会自动进入 snippet,snippet 里创建的局部变量也不会泄漏回调用文件。这种限制看似多写几项参数,实际上能减少“换个页面就突然取不到变量”的隐性依赖。

先看 Dawn 中真实的价格调用链

我在本地 Dawn 仓库提交 258f00f 中检查了 sections/main-product.liquidsnippets/price.liquid。商品主区域没有复制整套价格 HTML,而是把当前商品和显示选项传给价格 snippet:

{% render 'price',
  product: product,
  use_variant: true,
  show_badges: true,
  price_class: 'price--large'
%}

这段调用里,左侧的 productuse_variantshow_badgesprice_class 是 snippet 内部读取的参数名;冒号右侧才是调用位置提供的值。参数名不必和父级变量同名,但同名时更容易读懂。

Dawn 的 price.liquid 文件开头也列出了这些参数和调用示例。商品卡片 card-product.liquid 会调用同一个价格 snippet,却传入不同的显示选项。这正是 Shopify Liquid snippet 的典型价值:输出规则只维护一份,调用者明确决定本次需要哪些行为。

render 的隔离作用域怎样理解

假设 section 中先写了 assign sale_label = '促销',再执行 {% render 'price' %}。price snippet 不能仅凭父级存在这个局部变量就读取它;要使用它,应显式传入:

{% render 'price', product: product, sale_label: sale_label %}

反过来,snippet 内部的 assign 也不会改掉调用位置的同名局部变量。全局对象和当前模板可访问的对象另有规则,但在自定义 snippet 中仍建议把关键依赖写成参数。这样只看 render 这一行,就能判断该组件依赖什么。

实作:带 LiquidDoc 的商品价格提示

下面创建 snippets/product-price-note.liquid。它接收商品对象,并用可选布尔参数决定是否显示更高的划线价。示例没有替代 Dawn 完整价格组件的打算,只用于说明一条最小、可验证的参数链。

{% doc %}
Renders the selected variant price and an optional compare-at price.

@param {object} product - Product whose selected or first available variant supplies the price.
@param {boolean} [show_compare_at] - Whether to show a higher compare-at price.

@example
{% render 'product-price-note', product: product, show_compare_at: true %}
{% enddoc %}

{%- liquid
  assign current_variant = product.selected_or_first_available_variant
  assign current_price = current_variant.price | money
  assign compare_at_price = current_variant.compare_at_price
-%}

<p class="product-price-note">
  <span class="product-price-note__current">{{ current_price }}</span>
  {%- if show_compare_at and compare_at_price > current_variant.price -%}
    <s class="product-price-note__compare">{{ compare_at_price | money }}</s>
  {%- endif -%}
</p>

{% doc %}{% enddoc %} 是 LiquidDoc 文档区。它不参与店面输出,但能声明说明、参数类型、可选参数和示例。Shopify 的 Liquid VS Code 扩展可以据此提供悬停说明、补全和参数检查。对会长期维护的 snippet,这比只留一句“价格组件”更有用。

在商品模板或能取得 product 对象的 section 中,调用方式如下:

{% render 'product-price-note',
  product: product,
  show_compare_at: true
%}

这里有两个刻意的保护:先从商品取得 selected_or_first_available_variant,避免直接假设某个变体已被选中;只有划线价存在且高于当前价时才输出 <s>。正式项目还应根据现有主题的货币、税费、单位价格和无障碍规则决定是否复用 Dawn 的 price snippet,而不是盲目重写。

用 Shopify CLI 做 Theme Check

我把上述 snippet 放进一个最小主题结构,并从 section 真实调用它,然后使用本机 Shopify CLI 4.7.0 执行:

shopify theme check --path ./liquid-render-example 
  --output json 
  --fail-level error 
  --no-color

检查结果为 [],即 snippet 与调用文件没有 Theme Check offense。只校验单独的 snippet 时曾出现 OrphanedSnippet 警告,因为当时还没有文件引用它;补上真实 render 调用后警告消失。这也说明静态检查要尽量放在接近真实主题结构的上下文中。

如果需要进一步理解失败级别、warning 与 CI 退出码,可以继续看 Shopify Theme Check 使用教程

四个常见问题

  1. 以为父级局部变量会自动可用。 render 是隔离作用域,关键变量应作为命名参数传入。
  2. 参数名传错但没有立即报错。 Liquid 中未定义值常表现为空,页面可能只是少一块内容。用 LiquidDoc、Theme Check 和真实商品数据一起检查。
  3. 继续使用旧的 include 思路。 Shopify 已弃用 include,新代码应使用 render,并显式处理作用域。
  4. 在循环里层层 render。 snippet 本身可以复用,但深层嵌套和循环中的大量 render 会增加渲染开销。能在一次调用里完成的结构,不必为了“组件化”继续拆成多层。

snippet、section 和 block 怎么选

类型主要用途商家能否直接在主题编辑器配置
snippet复用局部 Liquid 输出和逻辑不能直接配置,由调用者传参
section组成页面的大区域,包含 schema可以
blocksection 内可添加、排序或复用的内容单元通常可以

如果内容需要商家添加、排序或调整设置,先考虑 section 或 block;如果问题是多个模板重复了一段输出,且输入可以通过参数说清楚,才优先考虑 snippet。关于三者在 Dawn 目录里的位置,可以接着看《Shopify Dawn 主题目录结构》;需要先理解编辑器中的层级,则参考《Shopify Section 与 Block 实战理解》

完成前检查清单

  • snippet 的必要输入都通过 render 参数显式传入;
  • 可选参数在未传入时也有安全行为;
  • LiquidDoc 与真实参数名、类型和示例一致;
  • 用真实商品、变体和价格状态检查输出;
  • Theme Check 无错误,并留意嵌套 render 的数量。

一个好用的 Shopify Liquid snippet 不只是“能被 render”,还应该让调用位置一眼看出输入,让文件内部不依赖隐含局部变量,并能通过文档和静态检查把错误提前暴露。先从价格或图标这样边界清楚的小组件开始,比一次拆完整张商品卡片更容易验证。

官方资料

数臻源码猫咪图标
目录
数臻源码猫咪图标

目录

标签云: