10.网页删除购物车餐品

删除购物车餐品

一、前端处理

在前端,我们的主要步骤是,添加点击事件,实现调用的函数。大多数的功能都是这两步就可以实现。

在删除处添加点击事件:

html 复制代码
<button onclick="delMulti()" type="button" class="btn btn-danger" 
style="width:80px;">删除</button>

第二步,实现delMulti函数:

javascript 复制代码
    const delMulti = async () => {
        const boxes = document.querySelectorAll(".my-box:checked");
        if (boxes.length === 0) {
            toast("错误!", "请选择要删除的商品!");
            return;
        }
        const idArgs = [...boxes].map(box => `meal_id=${box.value}`).join("&");
        const resp = await fetch(`cart/del?${idArgs}`);
        if (!resp.ok) {
            toast("错误!", "删除失败!");
            return;
        }
        const result = await resp.json();
        if (!result.success) {
            toast("失败!", result.message);
            return;
        }
        getList();
        toast("成功!", "删除成功");
    }

函数的解释:

  1. const boxes = document.querySelectorAll(".my-box:checked");:这行代码获取所有选中的 .my-box 类的复选框元素。其中.my-box:checked 用于选择具有 my-box 类且被选中的复选框(checkbox)元素。

    这里的 :checked 是一个伪类选择器,它匹配任何被选中的复选框或单选按钮(radio button)。

    具体来说,这个选择器的组成部分如下:
    .my-box:选择所有具有 my-box 类名的元素。
    :checked:从上述选中的元素中,进一步选择那些被用户勾选的元素。

  2. if (boxes.length === 0) { ... }:如果没有选中任何复选框,会显示一个错误提示,并返回,不执行后续操作。也就是用户没勾选任何一个商品自然也就不能进行删除操作了。

  3. const idArgs = [...boxes].map(box => meal_id=${box.value}).join("&");:这行代码将选中的复选框的值(假设每个复选框的 value 属性代表商品的ID)转换成查询参数字符串,用于构建请求URL。没学过可能难以理解。

    在这里拆开来理解:[...boxes]:使用扩展运算符(spread operator)将 NodeList 对象转换为数组。这是因为 NodeList 对象不是真正的数组,而是一个类数组对象,不能直接使用数组的方法如 map。
    .map(box => meal_id=${box.value}):使用 map 方法遍历数组中的每个复选框元素。对于每个元素,它创建一个字符串,格式为 meal_id=<box的value值>。
    .join("&"):使用 join 方法将数组中的所有字符串连接成一个单一的字符串,每个字符串之间用 & 符号连接。这样,如果有三个选中的复选框,其 value 分别为 1、2 和 3,最终生成的字符串将是 meal_id=1&meal_id=2&meal_id=3

  4. const resp = await fetch(cart/del?${idArgs});:使用 fetch API 发送一个请求到服务器的 cart/del 路径,并带上之前构建的查询参数,在这里就和之前的一样了。

  5. if (!resp.ok) { ... }:如果响应的状态码不是2xx(即请求失败),会显示一个错误提示,并返回。

  6. const result = await resp.json();:将响应体解析为JSON格式。

  7. if (!result.success) { ... }:如果响应的JSON中的 success 属性不是 true(即操作未成功),会显示一个错误提示,并返回。

  8. getList();:如果删除成功,调用 getList 函数,用于刷新或更新商品列表的函数。

  9. toast("成功!", "删除成功");:最后,如果一切顺利,会显示一个成功的提示。

到这里前端实现完成,开始实现后端逻辑

二、后端处理

这是关于购物车的操作,所以我们的功能实现要在CartServlet类中进行添加删除购物车餐品功能。专门的功能在专门的类中进行,代码结构,层次会比较清晰。

老配方,三步法:加注解路径,加case板块,实现核心逻辑功能函数。

  1. 加注解路径:
java 复制代码
@WebServlet({
        "/cart/list",
        "/cart/num",
        "/cart/del"
        })
  1. 加case板块:
java 复制代码
           case "/cart/del":
               cartDel(req, resp);
               break;
  1. 实现核心逻辑功能函数:
java 复制代码
   private void cartDel(HttpServletRequest req, HttpServletResponse resp) throws IOException {
       User user = (User) req.getSession().getAttribute("CurrUser");
       if (user == null) {
           MyWeb.printJson(resp, R.err("请先登录"));
           return;
       }
       String[] mealIds = req.getParameterValues("meal_id");
       if (mealIds == null || mealIds.length == 0) {
           MyWeb.printJson(resp, R.err("请选择商品!"));
           return;
       }
       String condition = Arrays.stream(mealIds).map(id -> "meal_id=" + id).collect(Collectors.joining(" or "));
       DaoCreater.currentDao().update("delete from t_shoppingcart where u_id = ? and (" + condition + ")", user.getU_id());
       MyWeb.printJson(resp, R.OK());
   }

简单进行一下函数解释:

  1. User user = (User) req.getSession().getAttribute("CurrUser");:从当前会话中获取当前用户对象。

  2. if (user == null) { ... }:如果当前会话中没有用户对象(即用户未登录),则返回一个错误响应,提示用户需要先登录。

  3. String[] mealIds = req.getParameterValues("meal_id");:从请求中获取名为 meal_id 的参数值数组。这个参数应该是我们前端发送过来的也就是URL后的参数,包含要删除的商品ID。

  4. if (mealIds == null || mealIds.length == 0) { ... }:如果没有提供 meal_id 参数,或者参数数组为空,则返回一个错误响应,提示用户需要选择商品。

  5. String condition = Arrays.stream(mealIds).map(id -> "meal_id=" + id).collect(Collectors.joining(" or "));:这个是使用Java 流(Stream)和lambda表达式构建一个SQL条件字符串。对于每个 meal_id,它创建一个条件子句 "meal_id=" + id,然后将所有子句用 " or " 连接起来,形成一个完整的SQL WHERE 子句条件。

    6. .map(id -> "meal_id=" + id):对流中的每个元素(在这个例子中是 mealIds 数组中的每个ID)应用一个映射函数。这个映射函数将每个ID转换为一个字符串,格式为 "meal_id=" + id。这是构建SQL查询条件的一部分。
    .collect(Collectors.joining(" or ")):收集流中的所有元素,并将它们连接成一个单一的字符串。Collectors.joining 是一个收集器,它将流中的字符串元素连接起来,并在每个元素之间插入指定的分隔符。在这个例子中,分隔符是 " or ",这意味着如果流中有多个元素,它们将被连接成一个由 " or " 分隔的字符串。

    例如,如果 mealIds 数组包含 ["1", "2", "3"],那么这行代码将生成字符串 "meal_id=1 or meal_id=2 or meal_id=3"。

  6. DaoCreater.currentDao().update("delete from t_shoppingcart where u_id = ? and (" + condition + ")", user.getU_id());:调用数据访问对象(DAO)来执行一个SQL更新(删除)操作。这个操作会从 t_shoppingcart 表中删除所有属于当前用户(u_id)且符合之前构建的条件的商品。

8. MyWeb.printJson(resp, R.OK());:最后,如果删除操作成功,返回一个JSON格式的成功响应。

如果函数理解的话,那么代码实现起来还是容易。

注意:在这里的直接将用户输入拼接到SQL查询中的做法存在SQL注入的风险,一般还是用参数化的查询较好。

到这里前后端的代码都已经完成了,唯一要做的就是根据报错的地方进行排查了,毕竟没有人能保证代码不出错,学会排查bug也是能力的体现。

相关推荐
新手小袁_J11 分钟前
JDK11下载安装和配置超详细过程
java·spring cloud·jdk·maven·mybatis·jdk11
呆呆小雅12 分钟前
C#关键字volatile
java·redis·c#
Monly2113 分钟前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
Ttang2315 分钟前
Tomcat原理(6)——tomcat完整实现
java·tomcat
钱多多_qdd26 分钟前
spring cache源码解析(四)——从@EnableCaching开始来阅读源码
java·spring boot·spring
waicsdn_haha28 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
web1478621072332 分钟前
C# .Net Web 路由相关配置
前端·c#·.net
m0_7482478033 分钟前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
飞的肖36 分钟前
前端使用 Element Plus架构vue3.0实现图片拖拉拽,后等比压缩,上传到Spring Boot后端
前端·spring boot·架构
Q_192849990638 分钟前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端