Ajax购物车 - shopi8 中文建站教程

Ajax购物车

摘要

18 Ajax购物车

先判断问题出现在哪里

传统的 Shopify 购物车体验是:点击加购 -> 页面白屏跳转到 /cart 页面 -> 如果想继续购物,点击浏览器的后退按钮。这种充满摩擦的流程会扼杀用户的连带购买欲。

Ajax购物车的四项 Shopify 检查清单
Ajax购物车的四项 Shopify 检查清单

核心逻辑是:通过 Shopify Storefront Cart API 实现无刷新数据交互。

利用 JavaScript 的 fetch API,在后台默默地向 Shopify 发送加购、更新数量、删除商品的请求。拿到返回的最新购物车 JSON 数据后,使用 DOM 操作或现代前端框架(如 Vue/Alpine.js)局部更新页面右上角的购物车数量角标,并滑出一个精美的抽屉式购物车(Drawer Cart)。

实战步骤

步骤 1:拦截默认的表单提交 (Prevent Default)

操作路径在 product-form.js 中编写监听逻辑

  1. 找到产品页的加购表单(<form action="/cart/add">)。
  2. 监听 submit 事件,并阻止其默认的跳转行为:
    form.addEventListener('submit', async (e) => {
      e.preventDefault();
      const formData = new FormData(form);
      // 执行 Ajax 加购逻辑...
    });

步骤 2:调用 Cart API 添加商品

操作路径使用 fetch 发送 POST 请求

  1. Shopify 提供了极其简单的 Ajax API 接口。
    fetch(window.Shopify.routes.root + 'cart/add.js', {
      method: 'POST',
      headers: { 'X-Requested-With': 'XMLHttpRequest' },
      body: formData
    })
    .then(response => response.json())
    .then(item => {
      console.log('加购成功:', item.title);
      // 触发打开抽屉购物车的事件
      openCartDrawer();
      // 刷新购物车数据
      refreshCart();
    })
    .catch(error => console.error('加购失败:', error));

步骤 3:获取并渲染最新的购物车数据

操作路径调用 GET /cart.js 接口

  1. 加购成功后,需要获取购物车里的所有商品来渲染抽屉。
    fetch(window.Shopify.routes.root + 'cart.js')
    .then(response => response.json())
    .then(cart => {
      // cart.item_count 是总数量,更新右上角角标
      document.querySelector('.cart-count').textContent = cart.item_count;
      
      // 遍历 cart.items 数组,拼接 HTML 字符串,渲染到抽屉的列表中
      renderCartItems(cart.items);
      
      // 更新底部总价
      document.querySelector('.cart-total-price').textContent = formatMoney(cart.total_price);
    });

步骤 4:在抽屉内实现数量修改与删除

操作路径调用 POST /cart/change.js 接口

  1. 在抽屉里,每个商品旁边都有 +- 按钮。
  2. 当用户点击 + 时,获取该商品的 key(购物车中该行的唯一标识)和新的数量。
  3. 发送请求更新数量:
    fetch(window.Shopify.routes.root + 'cart/change.js', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id: itemKey, quantity: newQuantity })
    })
    .then(...) // 重新调用 refreshCart() 刷新整个抽屉
  4. 删除商品就是将 quantity 设为 0

常见误区与处理方法

误区一:使用纯 JS 拼接复杂的 HTML 导致代码难以维护 (XSS 风险)

规避方法:在上面的步骤 3 中,如果你用原生的 JavaScript 去遍历 cart.items,然后写出像 html += '<div class="item"><h3>' + item.title + '</h3></div>' 这样的代码,这不仅极其痛苦、难以维护,还存在严重的 XSS 跨站脚本攻击风险。现代 Shopify 主题开发,强烈建议使用 Section Rendering API 来代替纯 JS 拼接。 你可以请求 /?section_id=cart-drawer,让 Shopify 服务器直接用 Liquid 渲染好抽屉的 HTML 代码返回给你,前端只需做一次 innerHTML 替换即可。这既保证了代码的整洁,又完美复用了 Liquid 的各种过滤器(如价格格式化、图片裁剪)。

误区二:忽略了 Ajax 请求的并发冲突 (Race Conditions)

规避方法:用户在抽屉里疯狂点击 + 按钮,一秒钟内点了 5 次。由于网络延迟,这 5 个 Ajax 请求到达服务器和返回的顺序可能是错乱的。最终购物车里显示的数量和总价会完全对不上。在处理购物车数量更新时,必须加入防抖(Debounce)机制或请求锁定(Loading State)。 当用户点击 + 后,立刻将整个抽屉加上半透明的 Loading 遮罩,并禁用所有按钮,直到收到服务器的成功响应后,再解除锁定。确保同一时间只有一个购物车修改请求在处理。

误区三:多语言/多货币环境下的路由前缀丢失

规避方法:在写 fetch 请求时,很多新手习惯直接写 fetch('/cart/add.js')。这在单语言店铺没问题。但如果店铺开启了 Shopify Markets,用户切换到了法语版(URL 变成了 yourstore.com/fr)。此时你再请求 /cart/add.js,会报 404 错误或者丢失语言上下文。永远、永远不要硬编码绝对路径! 必须使用 Shopify 注入到全局的路由变量:fetch(window.Shopify.routes.root + 'cart/add.js')window.Shopify.routes.root 会自动带上当前的语言前缀(如 /fr/),确保 Ajax 请求在任何国际化环境下都能精准命中正确的接口。

Ajax购物车从判断到验证的三步执行路径
Ajax购物车从判断到验证的三步执行路径

FAQ

Ajax购物车应该先检查什么?

先在测试主题或测试页面中操作,并保留修改前版本和验证记录。不要同时改很多位置,先记录当前页面和数据,再处理最明确的问题。

需要马上安装新的 Shopify App 吗?

不一定。先判断主题现有功能、后台字段和少量代码能否解决。只有需要持续同步数据或复杂自动化时,再评估 App 的费用、脚本负担和卸载影响。

修改后怎么验证是否有效?

记录修改日期、页面 URL 和改动内容,再用实际页面、移动端、Google Search Console、Bing Webmaster Tools 或 GA4 检查结果。技术修改还要保留测试记录和回滚版本。

哪些情况不建议马上修改?

数据量太少、追踪没有配置、问题还没有复现,或者正在进行大型主题更新时,不建议一次性重做。先把问题拆开,确认影响范围后再改。

下一步阅读

分享这篇文章

阅读说明

这些文章更适合当作排查笔记,而不是万能模板。

这篇文章适合怎么读?

先看结论和步骤,再对照自己的网站情况判断是否适用。涉及代码或后台设置的部分,建议先在预览主题或测试环境里试。

可以直接照着改吗?

有些步骤可以直接参考,有些要看主题结构、App、页面内容和当前业务阶段。不要在正式主题上直接试,先备份或用预览主题验证。

代码片段需要注意什么?

不同主题的 section、snippet 和 CSS 结构不一样。复制代码前先确认文件位置和命名,改完后检查桌面端、移动端和购物流程。

后续还会补充吗?

会。内容会围绕建站流程、主题代码、页面优化、速度排查和工具实测慢慢补,不追热点,优先写实际遇到的问题。

我的情况和文章不一样怎么办?

可以先把网站链接、页面现象和你已经尝试过的操作记下来,再决定是继续自查,还是发来让我帮你判断问题类型。

继续看 Shopify 实操笔记

如果这篇文章解决了一部分问题,可以回到博客列表继续看相关笔记;如果情况不一样,再带着页面和现象来判断。

返回博客列表 发来问题