先判断问题出现在哪里
市面上的 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)确保渲染出来的商品卡片直接锁定在用户收藏的那个特定颜色和尺码上。
常见问题
学习「零插件实现 Shopify 愿望清单 (Wishlist) 功能开发」前需要什么基础?
建议先熟悉 HTML、CSS、基础 JavaScript 和 Shopify 后台结构。涉及 Liquid、Section、Schema 或主题工作流的内容,可以边读边在测试主题里练习,不要直接改线上主题。
可以直接在正在使用的线上主题里操作吗?
不建议。主题开发和结构调整应先在复制主题、开发主题或本地环境中完成,确认移动端、产品页、购物车和关键模板正常后,再发布到线上主题。
修改主题前最应该备份什么?
至少保留当前主题副本,并用 Git 记录代码变化。如果文章涉及主题编辑器配置,还要注意模板 JSON 和 settings_data.json 这类配置文件是否需要同步。
遇到教程和后台界面不一致怎么办?
优先以当前 Shopify 后台、主题代码和官方文档为准。Shopify 后台和 CLI 会持续更新,旧截图可用于理解路径,但不能替代当前界面提示。
这类主题开发内容适合什么时候上线到正式店铺?
当改动已经在测试主题中完成移动端、桌面端、产品页、集合页、购物车和速度检查后,再安排上线。影响结账、价格、库存或应用兼容的改动要单独回归。