先判断问题出现在哪里
市面上的 Wishlist(愿望清单)插件通常每个月要收取 $10-$30 的订阅费,而且会向你的主题注入大量的外部 JS 和 CSS,拖慢网页加载速度。

核心逻辑是:利用浏览器本地存储(LocalStorage)或 Shopify 客户元字段(Customer Metafields)进行数据持久化。
作为一个优秀的主题开发者,你完全可以纯前端手写一个轻量级、零成本、极速加载的愿望清单功能。对于未登录的访客,将他们收藏的商品 Handle 存在浏览器的 LocalStorage 中;对于已登录的客户,通过 Storefront API 将数据同步到他们专属的 Customer Metafields 中,实现跨设备同步。
实战步骤
步骤 1:在商品卡片上部署“红心”收藏按钮
操作路径:在 snippets/product-card.liquid 中添加按钮
- 在产品图片右上角放置一个心形 SVG 图标按钮。
- 绑定核心数据属性:
data-product-handle="{{ product.handle }}"。 - 编写基础 CSS:默认是空心(描边),当按钮带有
is-active类时,变为实心红色。
步骤 2:编写 LocalStorage 存取逻辑 (访客模式)
操作路径:在 assets/wishlist.js 中编写核心逻辑
-
读取状态:页面加载时,读取
localStorage.getItem('shopify_wishlist')。如果存在,将其解析为数组(如['t-shirt-red', 'jeans-blue'])。遍历页面上的所有红心按钮,如果其 handle 在数组中,则添加is-active类,点亮红心。 -
切换状态 (Toggle):监听红心按钮的点击事件。
- 如果当前未收藏:将 handle 推入数组,保存回 LocalStorage,点亮红心。
- 如果当前已收藏:将 handle 从数组中剔除,保存回 LocalStorage,熄灭红心。
-
更新角标:获取数组的
length,更新网站右上角导航栏里 Wishlist 图标旁边的数字角标。
步骤 3:构建独立的“我的愿望清单”页面
操作路径:新建 page.wishlist.json 模板和对应的 Section
- 在 Shopify 后台创建一个名为 "Wishlist" 的普通页面,并分配给这个新模板。
- 在这个页面的前端 JS 中,读取 LocalStorage 里的 handle 数组。
- 数据渲染:如果数组为空,显示“您的愿望清单为空,去逛逛吧”;如果数组有值,我们需要获取这些商品的详细信息来渲染卡片。
- 批量获取商品数据:不要用循环发几十个 Ajax 请求!利用 Shopify 的搜索接口,将 handle 拼接成查询字符串:
fetch('/search?view=wishlist-ajax&type=product&q=handle:t-shirt-red OR handle:jeans-blue') - 创建一个隐藏的
search.wishlist-ajax.liquid模板,专门用于接收这个请求,并用 Liquid 渲染出这批商品的 HTML 卡片结构返回给前端。
步骤 4:进阶:客户 Metafields 同步 (登录用户模式)
操作路径:结合 Storefront API (GraphQL)
- LocalStorage 的致命弱点是:用户换个手机或清空浏览器缓存,收藏就全没了。
- 如果用户已登录(
{% if customer %}),在点击红心时,除了更新本地存储,还应该通过 Storefront API 发送一个 GraphQL Mutation。 - 将收藏的 handle 数组,保存到该客户的
customer.metafields.custom.wishlist字段中。 - 当用户在另一台设备登录时,优先读取 Metafield 中的数据并覆盖本地的 LocalStorage,实现完美的跨设备云同步。
常见误区与处理方法
误区一:使用 Ajax 循环请求每个商品的详细信息
规避方法:在步骤 3 渲染愿望清单页面时,很多新手会写一个 for 循环,遍历 LocalStorage 里的 10 个 handle,然后向 Shopify 发送 10 次 fetch('/products/' + handle + '.js') 请求,拿到 JSON 后再用 JS 痛苦地拼接 10 个商品卡片的 HTML。这会导致页面加载极其缓慢,且极易触发 Shopify 的 API 速率限制(Rate Limit)。必须使用批量查询架构。 利用 Shopify 的 /search 接口配合 OR 逻辑(如步骤 3 所述),一次性将所有需要的商品 HTML 渲染完毕并返回。这不仅速度极快,而且完美复用了主题原生的 product-card.liquid 样式。
误区二:页面缓存导致红心状态显示错误
规避方法:为了提升速度,很多 Shopify 商店开启了全页缓存(Full Page Caching)或使用了类似 Turbolinks 的页面预加载技术。这会导致用户从产品 A 页面点击后退返回集合页时,集合页上的红心状态依然是旧的(因为页面是从浏览器缓存中直接读取的,没有执行 JS 初始化)。在编写 Wishlist 的 JS 逻辑时,必须监听 pageshow 事件(尤其是 event.persisted 属性),或者监听 Turbolinks/Barba.js 的页面加载完成事件。 确保每次页面重新展示在用户面前时,都会强制重新读取一次 LocalStorage,并刷新所有红心按钮的亮灭状态。
误区三:忽略了变体 (Variant) 级别的收藏需求
规避方法:上述基础方案只存储了 product.handle(即收藏了整个产品)。但如果用户只想收藏这件衣服的“红色-XL”款呢?当他们进入愿望清单页面点击加购时,系统怎么知道他们想要什么颜色?对于服装等强变体属性的类目,Wishlist 必须升级为 Variant 级别。 在 LocalStorage 中存储的不再是单纯的 product-handle,而是 variant-id。在渲染愿望清单页面时,不仅要请求产品信息,还要通过 URL 参数(如 ?variant=123456)确保渲染出来的商品卡片直接锁定在用户收藏的那个特定颜色和尺码上。

FAQ
愿望清单功能应该先检查什么?
先在测试主题或测试页面中操作,并保留修改前版本和验证记录。不要同时改很多位置,先记录当前页面和数据,再处理最明确的问题。
需要马上安装新的 Shopify App 吗?
不一定。先判断主题现有功能、后台字段和少量代码能否解决。只有需要持续同步数据或复杂自动化时,再评估 App 的费用、脚本负担和卸载影响。
修改后怎么验证是否有效?
记录修改日期、页面 URL 和改动内容,再用实际页面、移动端、Google Search Console、Bing Webmaster Tools 或 GA4 检查结果。技术修改还要保留测试记录和回滚版本。
哪些情况不建议马上修改?
数据量太少、追踪没有配置、问题还没有复现,或者正在进行大型主题更新时,不建议一次性重做。先把问题拆开,确认影响范围后再改。