React项目(购物app移动端)
本文介绍了如何拆分一个购物App的UI组件,并实现购物车功能。主要步骤包括:1.拆分组件结构(搜索框、列表、购物车等);2.实现食物列表组件(Meals容器组件和Meal列表项);3.创建可复用按钮组件(使用FontAwesome图标);4.处理购物车状态逻辑(添加/删除商品的计算逻辑)。重点讲解了购物车数据的更新机制,包括状态管理、商品数量增减逻辑,以及通过props传递数据的局限性。文章展示了
这是我们的app效果图。
我们拿到了成品图,我们就需要去拆分成组件,首先第一个图片,我们拆分成三个组件,搜索框组件,列表展示组件,购物车组件,然后列表展示组件需要子组件作为列表的每一个元素。然后列表子组件的按钮都需要使用,所以也作为一个组件。这个按钮都可以使用,那么我们作为一个UI组件。购物车组件可以展开,展示购物车详情,这也是一个组件,然后套用列表组件,点击结算出现支付页面也是一个组件,包含的是购物清单,和支付按钮组件。
大概的组件关系图我们画一下
可能有问题不过先开始写吧,写的时候发现问题去改。
1.食物列表组件
搜索和购物车都需要食物列表中展示的数据,所以先写这个组件。

没什么好说的,一个Meals组件作为容器组件,Meal作为列表组件。遍历Meal展示。
首先根组件,我们要展示的数据,这里我们假设是服务器返回的数据,毕竟现在只是学习前端,然后我们去引入这个容器组件,把数据通过props传递过去,这样列表动态展示。

然后Meals组件遍历传过来的数组,把里面的每一个对象作为参数传递给Meal列表组件,然后列表组件就可以去展示了。
这里我们直接props接到对象,然后展示。这样我们的食物列表组件就完成了。
2.食物列表子组件按钮组件
食物列表-》食物-》按钮组件,那么我们开始吧。首先我们看模板图这个按钮大家都在用,那就放UI文件里面。

然后这个按钮
import React from 'react'
import classes from './Counter.module.css'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlus } from '@fortawesome/free-solid-svg-icons'
import { faMinus } from '@fortawesome/free-solid-svg-icons'
export default function Counter(props) {
return (
<div className={classes.Counter}>
{
(props.amount && props.amount !== 0) ? <>
<button className={classes.Sub}><FontAwesomeIcon icon={faMinus} /></button>
<span className={classes.count}>{props.amount}</span>
</> : ''
}
<button className={classes.Add}><FontAwesomeIcon icon={faPlus} /></button>
</div>
)
}
我们通过amount去判断是否展示我们的-号以及数字内容,有的话展示没有就不展示。注意我们现在的amount在我们食物组件传递的时候是没有这个值的,是undefined。

这里我们用文字去输入-和+很难去居中,那么我们就需要去引入一些图标,去更好的实现我们的样式需求。那么我们添加小图标就需要去外面引入一些库。
引入 FontAwesome
1.引入依赖
npm i --save @fortawesome/fontawesome-svg-core
npm i --save @fortawesome/free-solid-svg-icons
npm i --save @fortawesome/free-regular-svg-icons
npm i --save @fortawesome/react-fontawesome@latest
npm install @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/free-regular-svg-icons @fortawesomereact-fontawesome@latest
安装完依赖
引入组件
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
引入图标 icon属性
import { faPlus } from '@fortawesome/free-solid-svg-icons'
使用图标
<FontAwesomeIcon icon={faPlus} />
可以去官方fortawesome查看怎么引入,这里我们引入的免费icons,然后使用就是react通过组件去引入,然后通过属性去选择你要的图片,官方文档里面都可以搜索到,没什么好说的,只是知道流程就可以了。看官方文档跟着走。
3.按钮事件生成购物车动态展示需要的数据

画图,一定要坚持画思路。首先我们希望点击之后,购物车发生变化,
而且还有购物详情列表。那我们购物车就很明显需要一个state作为数据来源展示,首先总数number类型,总价格number类型,还需要所有被选中汉堡的数据类型数组对象,包括amount,而且按钮本身也需要amount去改变自己的样式。一步步来
先定义我们购物车想要展示就需要用到的数据。
const [car, setCar] = React.useState({
item: [],
totalAmount: 0,
totalPrice: 0
})
那么这里面所有的初始值都为空,我们就需要在点击事件发生的一瞬间给它加上点击事件发生时的meal,以及设置一个amount,以及price和amount累加。
const addCar = (meal) => {
console.log(meal);
//首先浅复制car 不然直接更新会覆盖丢失其他的
const newCar = { ...car }
//通过find发放去判断我现在添加的meal是不是已经有了,没有就添加然后amount设置为1有了就不用只需要amount++就ok了
const isHave = newCar.items.find((item) => { return (item.id === meal.id) })
if (!isHave) {
newCar.items.push(meal)
meal.amount = 1
} else {
meal.amount += 1
}
//总数加1
newCar.totalAmount += 1
//总价格加当前添加meal的价格
newCar.totalPrice += meal.price
//然后更新
setCar(newCar)
}
这就是完整的点击事件的js逻辑,点我们点击事件发生的时候,传当前发生的列表数据通过函数参数的形式,然后我们先浅赋值我们想要更新的对象,然后用find找到我们当前添加的列表id是不是已经有了,没有就添加进去meal,有的话只是数量加1,然后总数加1,总价格加当前列表的price。还是很简单的逻辑。
//减少商品的数量
const delCar = (meal) => {
const newCar = { ...car }
meal.amount -= 1
let newItems
if (meal.amount === 0) {
newItems = newCar.items.filter((item) => { return (item.id !== meal.id) })
} else {
newItems = [...newCar.items]
}
newCar.totalAmount -= 1
newCar.totalPrice -= meal.price
const newCar1 = {
...newCar,
items: newItems
}
setCar(newCar1)
}
那么减少按钮的逻辑呢,首先我们浅复制,然后点击事件发生就数量-1,然后我们去筛选出点击事件发生的列表,如果是0就踢出去,如果不是0,就原来的Items保留,只不过我们修改了items这个对象中的一个属性,所以我们需要覆盖掉之前的,而且totalAmount-=1以及totalPrice需要更改后保留,我们新定义一个对象,复制newCar,然后把newItems覆盖进去,然后更新car就完成了整个购物车的数据改变了。接下来展示就可以了。
但是有一个问题是,我们通过props传递函数,通过调用函数传参数的方式,实现子组件向父组件传递一些数据,这显然很麻烦,如果套了10层就需要一直传下去,不过这个就在下个博客解决吧。这里主要是项目实现了动态展示数据。以及添加删除的简单js逻辑。
更多推荐



所有评论(0)