Skip to main content
大多数套装应用构建套装的方式是把每个组件作为单独的购物车行添加,然后用它们自己设计的行项目属性把这些行关联起来。Shopify 的 Ajax API 把这些行交给购物车时不带任何”它们属于一起”的标识,所以默认情况下抽屉会把一个三件套装显示为三个不相关的商品,各自带有自己的价格和数量调节器。 setInternalProperties 就是你告诉购物车它们是一体的方式。

组合的工作原理

购物车根据两个规范属性来组合行。它不知道你的套装应用的属性名称,所以由你来翻译:读取应用写入的内容,然后用行转换把规范属性对盖章到每一行上。 这些通过 setInternalProperties 传递,而不是通过 Shopify。它们是仅用于渲染的覆盖层:永远不会进入 properties,永远不会持久化到 Shopify,也永远不会出现在订单上。

第 1 步:查明你的应用写入了什么

每个套装应用给属性起的名字都不同,所以先看一个真实购物车。在你的店面上添加一个套装,然后在浏览器控制台运行:
你要找的是套装各行共享的一个属性。它通常是一个隐藏属性(名称以 _ 开头),持有一个 ID、一个引用或套装的名称。典型的有 _bundle_id_bundle_ref_parent_id。记下确切的键名,以及是否有某一行被标记为主产品。

第 2 步:映射到规范属性

粘贴到 Cart settings → Custom script → Initialization,把属性名替换为你找到的名称:
这就是整个集成。一旦两行或更多行共享一个 ID,购物车就会把它们折叠成一个套装。
如果你的应用没有标记主产品,就完全省略 _aftersell_cart_bundle_role。购物车会为你挑选一个主行。

你会得到什么

行被组合后,主行会携带一个 bundle 对象,抽屉将套装渲染为单个商品:
  • 子项嵌套在主行之下,而不是显示为单独的行。
  • **数量是原子的。**更改套装的数量会按每个子项的 perAnchorQty 比例一起缩放所有成员,所以某组件数量为二的套装会保持这个二比一的关系。
  • **移除是原子的。**移除套装会在一次请求中移除所有成员行,而不会留下孤立的组件。
  • 只有一个价格行。显示什么遵循 Cart items 区块上的套装价格设置:所有成员的总价,或仅主产品的价格。

主行如何选定

主行是套装显示为的那一行。购物车按此顺序挑选:
  1. _aftersell_cart_bundle_role 设为 parent 的行。
  2. 否则,价格最高的成员。
  3. 否则,购物车中的第一个成员。
价格回退通常是正确的,因为套装应用往往把折扣放在主产品上。当不是这样时,请显式设置角色,例如当主产品是最便宜的商品或是免费的时候。

值得了解的规则

  • **套装至少需要两行。**只有一行携带套装 ID 时不会被处理,正常渲染。
  • **Shopify 原生套装已经被处理。**Shopify 本身标记为组件化的行会被此组合跳过并自动适配。你只需要为添加独立行的应用使用它。
  • **转换在每次渲染时运行。**保持它开销小且无副作用。不要在其内部调用操作或发起请求。
  • **合并是累加式的。**你的属性会与其他转换设置的属性合并。对同一个键的真正冲突,由最后注册的转换胜出。
  • **组合在隐藏和重命名之后、排序之前运行。**所以你用 setHidden 隐藏的行永远不会成为套装的一部分,而比较器看到的是主行,而不是子项。
**组合后的子项会离开 state.items。**一旦行被折叠进套装,只有主行出现在 getCart().items 和事件载荷中;子项移动到 anchor.bundle.children。它们也不再计入 itemCount购物车总额不受影响,因为总额直接来自 Shopify。组合只改变展示,永远不改变购物者支付的金额。

读取套装

要对套装的行进行操作,请使用 bundle.memberKeys,它持有包括主行在内的每个成员的 key

用于其他用途

套装组合是 setInternalProperties 的设计初衷,但这个覆盖层是一个通用通道,用于你从行派生出的仅用于渲染的数据。你放在那里的任何东西都可以在 line.internalProperties自定义代码区块中读取,而不触及真实购物车:
当值是派生的且仅用于显示时使用它。如果数据需要保留到订单,它应该是一个真正的行项目属性,在产品表单上通过一个隐藏的 properties[...] 输入设置,这样无论由谁执行添加,值都能到达 Shopify。

后续阅读