添加购物车
- 一、引言
- 二、前端
- 2.1引入轻组件
- 2.2为图片添加点击事件
- 2.3创建addShoppingCart函数
- 三、后端
- 四、运行效果
- 五、导航条跳转
一、引言
在前几篇文章中,我们一步一步慢慢的实现了项目的建立,从数据库获取数据显示在页面,商品大图查看,查询和商品分页功能,以及登录退出,涉及一些模态框和轻组件的使用。到这里应该对于前后端的数据的交互比较了解了,从后端到前端再到我们所看见的网页,就是这样一步一步建立起来的。
你眼中所看到的效果功能是怎么实现的,
在学习的过程中,会逐渐发现很多代码其实都是做重复的动作,只是对于细节的处理逻辑略有不同。
我们学习这个项目,并不是单单学习怎么去做这么个商城项目,我们更多的是学他们的代码的逻辑,前后端怎么一起实现的功能,去理解代码为什么这么写,去学习他们代码的架构,层次。一句话,学习怎么学习!
二、前端
现在我们来实现添加购物车:把商品添加到购物车中去。
目的:用户点击商品卡片那个购物小车,完成该商品的购物车添加,针对成功与否提示相关信息。
2.1引入轻组件
在首页index.html,根据自己网页来,引入轻组件用来提示操作信息,前面也引入过,不多叙述了。
两步:
- 引入组件代码。
<div class="toast-container position-fixed top-0 start-50 translate-middle-x mt
1">
<div id="toast" class="toast opacity-100 bg-white">
<div class="toast-header">
<strong class="me-auto"></strong>
<button type="button" class="btn-close" data-bs-dismiss="toast">
</button>
</div>
<div class="toast-body"></div>
</div>
</div>
- 组件转换对象,创建函数来自定义显示提示。
//创建轻组件对象
const toastObj = new bootstrap.Toast(document.querySelector(`#toast`), {delay: 2200});
const toast = (title = "信息", msg = "") => {
document.querySelector('#toast .me-auto').innerHTML = title;
document.querySelector('#toast .toast-body').innerHTML = msg;
toastObj.show();
}
2.2为图片添加点击事件
<img onclick="addShoppingCart(${list[i].meal_id})"
src="./images/shopping-cart.png" style="height:35px;cursor: pointer;"
class="pe-1">
这里是为小车图片添加onclick属性,实现点击调用添加购物车函数。
其中参数是商品的id,从list对象中获取,list是我们在getMealList函数中建立的:
const list = pageObj.recList;
而其中recList中数据是这样的:
在这里给大家回忆一下,避免产生疑惑哪来的list[i]。
2.3创建addShoppingCart函数
接下来,在上面调用了addShoppingCart函数,所以现在来实现这个函数。
const addShoppingCart = async(meal_id) => {
const resp = await fetch(`./meal/add-cart?meal_id=${meal_id}`);
if (!resp.ok) return;
const result = await resp.json();
if (!result.success) {
toast("错误", result.message);
console.log("错误", result.message);
return;
}
toast("成功", "加购物车成功");
};
- 将meal_id通过fetch函数,指定路径包含参数像后端发起请求,返回响应。
- 判断响应状态,解析json数据,判断数据对象,根据result.success做出不同的提示,调用组件函数显示不同的提示。
前面类似的写过,所以这里简单叙述。
前端就完成了。
现在来实现后端的逻辑。
三、后端
- 老规矩,一个新的功能方法,我们先添加新的路径在WebServlet注解中:
"/meal/add-cart"
- 在判断路径的switch分支结构中也加上新的case板块:
case "/meal/add-cart":
mealAddCart(req, resp);
break;
- 最后实现mealAddCart函数:
private void mealAddCart(HttpServletRequest req, HttpServletResponse resp) throws IOException {
User user = (User) req.getSession().getAttribute("CurrUser");
if (user == null) {
MyWeb.printJson(resp, R.err("请先登录!"));
return;
}
String meal_id = req.getParameter("meal_id");
String selSql = "select sm_store from t_meal where meal_id = ?";
Dao dao = DaoCreater.currentDao();
int meal_num = dao.queryInteger(selSql, meal_id);
if (meal_num < 1) {
MyWeb.printJson(resp, R.err("库存不足!"));
return;
}
String updSql = "update t_shoppingcart set s_num = s_num + 1 where u_id = ? and meal_id = ?";
int count = dao.update(updSql, user.getU_id(), meal_id);
if (count == 0) {
String insSql = "insert into t_shoppingcart (u_id,meal_id,s_num) values(?,?,1)";
dao.update(insSql,user.getU_id(),meal_id);
}
MyWeb.printJson(resp,R.OK());
}
- 加购物车之前我们得判断有没有用户信息,也就是有没有登录,没有就要在返回的响应中告诉前端,让前端来处理。
如果登录了,就开始获取请求中包含的数据。其中getParameter 方法返回与指定参数名称相关联的值。如果请求中不存在该参数,它将返回 null。通常用于从表单提交或URL中读取用户输入的数据,然后根据这些数据进行进一步的处理。我们在URL中参数名是meal_id,所以我们指定获取参数meal_id。 - 定义sql语句用来查询数据库中的库存量,sm_store是我们在数据库存储库存量的变量名,在这里? 是一个占位符,用于后续的参数绑定以防止SQL注入攻击,
queryInteger(selSql, meal_id);
会执行sql语句进行数据库查询,meal_id会取代?的位置组成完整的sql语句。 - 接下来判断获取的库存量,没有了就返回响应告诉前端,我没货了,让前端在告诉用户。如果有库存就进行继续。
- 既然库存有,那么我们就要像购物车中更新数据,没数据就添加数据。
查询t_shoppingcart表中指定u_id和meal_id的s_num,就是说查找这个用户有没有这款商品,有就让数量加一,没有就就什么也不做,在这里count是所影响的行数。 - 后续判断等于0,那么说明u_id和meal_id相关联的数据没有,也就是此前这个用户没添加过该商品到购物车。所以向表中u_id和meal_id相关联的s-num数据设置为一,执行sql操作。
最后完成后返回包含成功的响应给前端处理。
到这里就完成了。
可以启动项目查找bug了[坏笑],如果运行不成功的话。
其实这里有个疑问,购物车数据增加了,库存的数据是不是应该减少相应的,后续再说吧。
四、运行效果
- 没登录之前添加购物车:
- 登陆后添加购物车:
还有库存不足,应该也没有问题。那么就基本实现了。
五、导航条跳转
在首页我们还有一些导航条没实现跳转,以及其他页面跳转需要完成,同时getCurrUser函数也需要复制到其他页面以显示当前用户,我们先完成这些繁琐的工作。
看过前面的应该自己就会加了,这里直接上部分代码为例:
<ul class="nav nav-pills ms-5">
<li class="nav-item">
<a class="nav-link bg-white text-danger fw-bolder" href="index.html">首页</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="cart.html">购物车</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" href="order.html">订单</a>
</li>
</ul>
在href属性添加其他相应网页html文件就行了。
提一句:这里这些都是<a标签的,所以自带超链接,不需要像按钮那样加onclick属性。