跳转到内容

动手做:购物车 题目

截止目前,你已经学习了基本的 React 知识,现在,让我们一起来创建一个 购物车 组件。

目标

你的目标是一比一复刻下面的 购物车 组件。

水果商城 🍎

购物车
总价:$0

要求

  • 新建一个 React 页面并绑定到 /cart 路由
  • 在主页添加一个按钮跳转到 /cart

/cart 页面

  • GET 读取 https://junxuanb.com/api/products.jsonproducts 的数据
  • 展示每个商品的数据,其中 discount 表示打折的金额
  • 对于不打折的商品,直接展示 price 即可
  • 对于打折的商品,首先,你应该用中划线划掉原来的单价。然后,使用高亮展示真实单价。你应该使用 price 减去 discount 来计算真实单价。
  • 商品展示中有一个 加入购物车 按钮,点击后,将商品加入购物车并且库存减少
  • 购物车中每个商品有三个按钮:+-删除,分别用于增加数量、减少数量、删除商品,操作后也应该对库存进行相应的增减
  • 购物车底部实时计算总价
  • 购物车底部有一个 结算 按钮,点击后,将购物车中的商品结算并且跳出提示框

提示

浮点数精度问题

在处理 Cherry 时,它的真实价格应该是 2.99 - 0.3 = 2.69,如果你得到 2.6900000000000004,这是因为 TypeScript 的浮点数精度问题,你可以使用 npm install decimal.js 安装 decimal.js 并使用它来处理浮点数运算,例如 new Decimal(2.99).minus(0.3).toNumber()

深拷贝

在对于一个 useState 的数组进行变更时,你可以需要先对这个数组进行一些操作,然后再存入,这时候你需要进行一个 深拷贝 操作。给你举个例子:

const [cart, setCart] = useState<Product[]>([]);
const newCart = cart;
// ... 对 newCart 进行一些操作,例如 .forEach()、.push() 等
setCart(newCart);

这样的操作会出现问题! 因为 newCart 本质上只是一个指向 cart 的引用,换而言之,改变 newCart 的内容是在尝试直接改变 cart 的内容。这是不合法的。因此我们需要:

const [cart, setCart] = useState<Product[]>([]);
const newCart = [...cart]; // 进行深拷贝,而不是直接引用
// ... 对 newCart 进行一些操作,例如 .forEach()、.push() 等
setCart(newCart);

这样就可以避免通过不合法的方式直接改变 cart 的内容了。