Skip to main content
事件让你响应购物车,操作让你更改购物车,而 hooks 则改变购物车本身的行为方式:行如何渲染、携带什么数据,以及加入购物车时会发生什么。 Hooks 位于 window.aftersell.cart.hooks 下。
Hook 改变的是购物者看到的内容;操作改变的是购物车里的内容。用转换隐藏免费赠品行,它仍留在购物车中并计入总额。用 removeItem 移除它才是真正拿出来。
Hooks 是设置类调用,所以可以安全地在脚本最顶部注册,无需等待 ready()。在你购物车的 Initialization 脚本中注册它们(参阅自定义脚本)。

注册的工作方式

每个 hook 都是一个 register* 方法。你用自己的函数调用它;它返回一个注销函数,调用即可移除你的注册。
注册是累加式的,所以你的函数会与其他所有函数一起运行。这很重要,因为你的脚本很少是页面上唯一的脚本:订阅应用、套装应用和主题本身可能都针对同一个 hook 注册。它们谁都不能替换你的,而在你之后加载的任何东西也不能静默丢弃你注册的内容。 抛出错误的 hook 或不是函数的 hook 会被跳过;其余照常运行,购物车继续工作。一个损坏的集成无法搞垮加入购物车、订阅选择器或排序。 反过来说,你自己损坏的 hook 会静默失败:什么都不会到达浏览器控制台。参阅调试了解这些失败在哪里显现。

registerLineTransform

registerLineTransform(fn) 在每个购物车行渲染之前运行。用它来隐藏某行或改变其显示方式,而不触及购物者购物车中的实际内容。 该函数接收一个只读的行加上一组 setter。它返回一个注销函数。
转换只改变渲染的内容。它不能更改价格、数量或行的身份。这些请使用操作
**适用场景:**隐藏随购赠品或应用注入的行、重新标记订阅行、标记折扣商品、隐藏购物者不应单独管理的套装组件。 setInternalProperties 是套装组合背后的 setter:将规范的套装属性盖章到每一行上,就是让第三方应用的多个独立购物车行渲染为一个商品的方式。参阅组合来自其他应用的套装行

registerLineComparator

一个与 Array.prototype.sort 期望的形式相同的比较器。它在隐藏和重命名之后运行,所以看到的是转换后的行。
比较器作为决胜规则组合:第一个返回非零值的比较器决定这一对的顺序,其余的只在平局时被咨询。对你没有意见的对返回 0。这样就把决定权交给下一个比较器,而不是强加一个顺序。 **适用场景:**将订阅或高价值商品浮到顶部、将免费赠品和附加产品沉到底部、让赞助产品保持第一位。

registerCartEnricher

registerCartEnricher(registration) 从 Shopify Storefront API 获取额外的产品或变体数据,并将其附加到每个匹配的购物车行的 line.metadata[id] 上。用它来展示元字段、标签或 Storefront API 暴露的任何其他内容,无需 Aftersell 做任何代码改动。 返回一个注销函数 每当购物车加载或变化时,Aftersell 会为购物车上的每个产品或变体获取你的片段并附加结果。获取是非阻塞的:购物车立即渲染,数据到达后重新发出 cart_updated。缓慢或失败的片段永远不会延迟或破坏购物车。
由于增强是异步的,读取时务必加防护,因为在首次获取完成之前 line.metadata.pricingundefined,而 metadata 本身默认为 {} **适用场景:**把元字段拉到每一行上(配送预估、成分列表、“单独发货”标志、忠诚度倍数),并通过自定义代码区块渲染。参阅在购物车行上显示元字段数据
多个增强器可以愉快共存,因为每个 id 是自己的命名空间,它们的数据永远不会冲突。
增强的值从 Storefront API 原样返回,未经消毒。请将它们渲染为文本,而不是原始 HTML。

registerSubscriptionOptionsTransform

隐藏或重命名某行提供的销售计划。你的函数接收只读的选项加上 setter,不返回任何内容。
**使用 setter 而不是返回列表,是为了让多个脚本能够共存。**如果这个 hook 返回一个数组,一个只关心某个计划的转换会自然地写 options.filter(...),从而在不经意间静默删除其他所有应用的计划。使用 setter,你只能描述你自己的修改:补丁按计划、按字段合并,同一计划同一字段上的真正冲突由最后写入者胜出。抛出错误的转换不贡献任何内容,其他转换仍然生效。 每个转换看到的都是原始选项,而不是打了一半补丁的视图,所以注册顺序不会改变你读到的内容。
计划顺序保持 Shopify 返回的样子,所以转换无法重新排序。要控制首先提供哪个计划(以及一次性购买升级按钮订阅哪个计划),请使用 registerDefaultSubscriptionOptionSelector,它会将其选择提升到最前面。
你也不能添加计划或更改价格:discountPercent 没有 setter,因为 Shopify 在结账时不会兑现的计划,在选择器中只会是一个空头承诺。

registerDefaultSubscriptionOptionSelector

选择在某行上预选哪个计划。返回一个计划 id,或返回 null 表示放弃选择。
第一个返回可用计划 id 的选择器胜出,所以对你不关心的行返回 null,而不要猜测。这样就把决定权交给下一个选择器,而不是覆盖它。与该行上任何计划都不匹配的 id 会被视同 null 并同样让位,所以过期的 id 不会把选择器清空。 你的函数接收 (options, context),与选项转换获得的 context 相同。

registerSkipAddToCartRule

返回 true 可以让特定的产品表单正常加入购物车,完全绕过 Aftersell。这对需要自己的重定向或处理的表单很有用。
任何 true 都会跳过,所以让你的规则保持窄范围,只匹配你拥有的特定表单,对其他一切返回 false。规则按注册顺序求值并在第一个 true 处停止,所以不要在规则中放副作用:你的规则是否运行,取决于在它之前注册了什么。
如果你能控制表单的标记,你根本不需要 hook:给 <form> 添加类 aftersell-cart-skip-atc,Aftersell 就不会碰它。当你无法编辑标记,或决定取决于只有你的代码才知道的东西时,才使用这个 hook。
**适用场景:**需要自己重定向的预购或询价表单、订阅应用的自定义流程、应直接进入结账的”立即购买”按钮。要为整个页面关闭拦截,请改用 skip_add_to_cart_interceptor,但优先使用这个 hook,因为它的作用范围限定在你指定的表单。

后续阅读