IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 图书商城_day4遇到的难点 -> 正文阅读

[数据结构与算法]图书商城_day4遇到的难点

将商品添加到购物车

我希望最后实现的界面是如下的界面:
在这里插入图片描述
其中购买数量中的两个按钮(变化值为1,点击’-‘,是减1,如果点击’+',那么是加1),可以修改中间文本框的购买数量,然后同时将小计进行修改。与此同时,如果我们直接来修改中间的文本框的数量,那么也会更新小计。所以关键是怎么处理这个呢?

  • 首先,我们定义了一个Cart类,表示我们的购买商品,其中在这个类中,存在着购买的商品Book,以及购买的数量count。对应的代码为:
package entity;
public class Cart {
    private Book book; //购物图书
    private int count;//购买的数量

    public Cart() {
    }

    public Cart(Book book, int count){
        this.book = book;
        this.count = count;
    }

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "Cart{" +
                "book=" + book +
                ", count=" + count +
                '}';
    }
    //获取总计,即book.price * count
    public double getTotal(){
        if(this.book == null){
            throw new RuntimeException("没有购买图书");
        }
        return this.book.getPrice() * this.count;
    }
}

  • 其次,我们定义一个CartList类,表示我们的购物车,其中在这个类中,定义了一个哈希表,表示我们的Cart,但是由于HashMap是无序的,即添加的顺序和在哈希表中的顺序是不一致的,因此为了维持两者的一致,那么我们需要使用的是LinkedHashMap.然后再这个类中,我们需要定义添加购物商品的数量,减少购物商品数量等方法。
package dao;

import entity.Cart;

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

/*
购物车:
用于对购买的商品进行增删改查操作
其中当用户登录之后,就会分配有一个购物车,所以我们再用户登录之后,
就给这个session添加一个购物车,也即CatrItems,然后调用相应的
方法进行相关的操作
 */
public class CartList {
    /*
    因为HashMap是根据哈希码来进行插入的,所以这时候添加商品的顺序和再map中的顺序
    是不一样的,因此为了保证两者一致,那么需要使用的是LinkedHashMap
     */
    private HashMap<Integer,Cart> cartItems = new LinkedHashMap<>();//键表示购买的图书id,Cart表示购买的图书以及购买数量
    public HashMap<Integer,Cart> getCartItems(){
        return cartItems;
    }
    //添加购物车(这个商品已经存在了)
    public void addItem(int id,int count){
        Cart old_cart = cartItems.get(id);
        old_cart.setCount(old_cart.getCount() + count);
    }

    //添加购物车(如果没有存在id这个cart的话,那么直接将当前的cart添加)
    public void addItem(int id,Cart cart){
        cartItems.put(id,cart);
    }
    //将购物车中的某一个商品数量减一
    public void subItem(int id,int num){
        //判断是否存在这个商品
        if(cartItems.containsKey(id)){
            //如果购买了这个商品,比较购买数量和减少数量
            Cart old_cart = cartItems.get(id);
            int count = old_cart.getCount();
            if(count > num){
                count -= num;
                old_cart.setCount(count);
                cartItems.put(id,old_cart);
            }else{
                throw new RuntimeException("购买的商品数量小于等于减少数量,无法减少商品");
            }
        }else{
            throw new RuntimeException("没有购买这个商品,无法减少该商品购买数量");
        }
    }
    //清空购物车
    public void clearItems(){
        cartItems.clear();
    }
    //获取购物车的总计
    public double getTotla(){
        double total = 0;//购物车中所有商品的总计
        for(Cart cartItem : cartItems.values()){
            total += cartItem.getTotal();//单个商品的小计
        }
        return total;
    }

    public int getSize(){
        //获取购物车的元素个数
        return cartItems.size();
    }

    //设置某件商品的属性(利用修改文本框中的数量的时候,需要利用这个方法来更新商品)
    public void setItem(int id,int count){
        //获取这件商品的id
        if(cartItems.containsKey(id)){
            Cart old_cart = cartItems.get(id);
            old_cart.setCount(count);
        }else{
            throw new RuntimeException("购物车中不存在这个商品,无法修改商品数量");
        }
    }

}

  • 我们定义一个CartServlet,用于和前台的交互,对应的代码
package web.servlets;

import dao.CartList;
import entity.Book;
import entity.Cart;
import service.BookService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;

public class CartServlet extends BaseServlet {
    private BookService service = new BookService();
    //添加商品的数量(点击'+'来增加的)
    public String addItem(HttpServletRequest request, HttpServletResponse response){
        //获取当前用户登录的cartList对象,否则,如果是新建的话,那么就会导致当前用户的购物车一直为空
        CartList cartList = (CartList)(request.getSession().getAttribute("cartList"));
        //获取添加的商品对应的id
        String value = request.getParameter("id");
        if(value == null){
            throw new RuntimeException("添加商品到购物车时没有传递参数id");
        }
        int id = Integer.parseInt(value);
        //添加的数量
        value = request.getParameter("count");
        int count = 1;//如果没有传递参数count,那么默认是1
        if(value != null){
            //传递了count,那么就需要进行更新count
            count = Integer.parseInt(request.getParameter("count"));
        }
        HashMap<Integer, Cart> cartItems = cartList.getCartItems();
        if(cartItems.containsKey(id)){
            cartList.addItem(id,count);
        }else{
            //获取这个id对应的图书
            try {
                Book book = service.queryById(id);
                cartList.addItem(id,new Cart(book,count));
            } catch (IOException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //添加完毕之后,来到cart.jsp中
        return "d:/jsps/cart.jsp";
    }

    //减少商品的数量(点击 '-'来减少的)
    public String subItem(HttpServletRequest request, HttpServletResponse response){
        //获取当前用户登录的cartList对象,否则,如果是新建的话,那么就会导致当前用户的购物车一直为空
        CartList cartList = (CartList)(request.getSession().getAttribute("cartList"));
        //获取减少的商品对应的id
        String value = request.getParameter("id");
        if(value == null){
            throw new RuntimeException("减少商品时没有传递参数id");
        }
        int id = Integer.parseInt(value);
        //减少的数量
        value = request.getParameter("count");
        int count = 1;//如果没有传递参数count,那么默认是1
        if(value != null){
            count = Integer.parseInt(request.getParameter("count"));
        }
        cartList.subItem(id,count);
        return "d:/jsps/cart.jsp";
    }

    //直接来修改文本框的值
    public String changeItem(HttpServletRequest request,HttpServletResponse response){
        //获取当前用户登录的cartList对象,否则,如果是新建的话,那么就会导致当前用户的购物车一直为空
        CartList cartList = (CartList)(request.getSession().getAttribute("cartList"));
        //获取修改的商品id
        String value = request.getParameter("id");
        if(value == null){
            throw new RuntimeException("减少商品时没有传递参数id");
        }
        int id = Integer.parseInt(value);
        //修改的数量
        value = request.getParameter("count");
        int count = 1;//如果没有传递参数count,那么默认是1
        if(value != null){
            count = Integer.parseInt(request.getParameter("count"));
        }
        System.out.println("changeItem ------------" + id + ", " + count);
        cartList.setItem(id,count);
        return "d:/jsps/cart.jsp";
    }
}

  • 前台数据中主要的代码为如下:
html代码
<div id="right">
        <!--如果购物车不为空,并且购物车中的购买商品的元素个数不为0-->
        <c:if test="${not empty sessionScope.cartList  and sessionScope.cartList.size > 0}">
            <table>
                <thead>
                   <td>商品照片</td>
                   <td>商品名称</td>
                   <td>商品分类</td>
                   <td>商品单价</td>
                   <td>购买数量</td>
                   <td>小计</td>
                </thead>
                <c:forEach items="${sessionScope.cartList.cartItems.values()}" var="cart" varStatus="vs">
                    <!--cartItems是一个哈希表,所以通过values来获取所有的商品-->
                    <tr>
                        <td><img src="<c:url value='/images/${cart.book.name}.png'></c:url>"></td>
                        <td>${cart.book.name}</td>
                        <td>${cart.book.catagory_name}</td>
                        <td>¥ ${cart.book.price} 元</td>
                        <td>
                            <input type="button" id="sub_${vs.index}" onclick="subItem(${cart.book.id},${cart.book.price},${vs.index})" value="-">
                            <input type="text" id="count_${vs.index}" onchange="changeText(${cart.book.id},${cart.book.price},${vs.index})" value="${cart.count}" style="width: 50px;">
                            <input type="button" id="add_${vs.index}" onclick="addItem(${cart.book.id},${cart.book.price},${vs.index})" value="+">
                        </td>
                        <td><span id="subtotal_${vs.index}">${cart.total}</span></td>
                    </tr>
                </c:forEach>
            </table>
        </c:if>
    </div>

js代码:
<script type="text/javascript" src="<c:url value="/ajax.js"></c:url>"></script>
<script type="text/javascript">
    window.onload = function(){
        //加载分类的值
        request({
            method: "POST",
            resource: "/CatagoryServlet",
            params: "method=queryCatagories",
            returnType: "json",
            callback: function (data) {
                var left = document.getElementById("left");
                left.innerHTML = "";//清空所有的数据,然后添加超链接标签
                // var ul = document.createElement("ul");
                //  ul.style.listStyle = "none";
                var li = document.createElement("li");
                var a = document.createElement("a");
                var text = document.createTextNode("全部分类");
                a.appendChild(text);
                a.href = "/BookServlet?method=queryAll";
                li.appendChild(a);
                // ul.appendChild(li);
                left.appendChild(li);
                for(var i = 0; i < data.length; ++i){
                    var li = document.createElement("li");
                    var a = document.createElement("a");
                    var text = document.createTextNode(data[i].name);
                    a.appendChild(text);
                    a.href = "/BookServlet?method=queryByCatagoryId&id="+data[i].id;
                    li.appendChild(a);
                    left.appendChild(li);
                }
            }
        })
    }
    function getSubTotal(index,money) {
        var span = document.getElementById("subtotal_" + index);
        span.innerHTML = money;
    }
    function addItem(id,price,index) {
        var count_text = document.getElementById("count_" + index);
        var num = parseInt(count_text.value) + 1;
        count_text.value = num;
        request({
            method: "POST",
            resource: "/CartServlet",
            params: "method=addItem&id=" + id + "&count=1"
        })
        getSubTotal(index,price * num);
    }
    function subItem(id,price,index){
        var count_text = document.getElementById("count_" + index);
        var num = parseInt(count_text.value);
        if(num > 1){ //如果等于1,不可以再减了
            num = num - 1;
            count_text.value = num;
            request({
                method: "POST",
                resource: "/CartServlet",
                params: "method=subItem&id=" + id + "&count=1"
            })
            getSubTotal(index,price * num);
        }
    }

    function changeText(id,price,index){
        //改变文本框中的值
        var count_text = document.getElementById("count_" + index);
        /*
        注意是将count_index这个文本框的value转成int类型,
        否则,如果是parseInt(count),就会导致num是一个NAN
        */

        var num = parseInt(count_text.value);
        request({
            method: "POST",
            resource: "/CartServlet",
            params: "method=changeItem&id=" + id + "&count=" + num
        })
        //因为我们需要根据index来获取到对应的span标签
        getSubTotal(index,price * num);
    }
</script>

前端代码中关键的地方:

  • 首先,因为我们需要每一个表格中都存在‘-’,‘+’这两个按钮,所以我们不可以将button的id为add之类的,所以为了保证维持每一个button的id是唯一的,我们需要利用<c:forEach>标签中的varStatus,这样就可以利用这个属性中的index,来获取遍历元素当前的下标,这样只要在id的后面添加这个index后缀,就可以保证每一个button的id是唯一的
  • 在上面之后,我们的js代码中,如何保证点击的是哪一个button呢?这时候我们就需要给点击事件中传递vs.index,这样就可以保证了我们点击的是哪一个按钮,这样就可以触发对应按钮的点击事件。
  • 点击完毕之后,就需要利用ajax来局部更新html,然后再调用getSubTotalb方法,来更新对应的小计
  • 但是需要注意的是,我们需要保证我们定义的方法addItem,subItem,changeItem方法不是定义再window.onload的方法里面,否则就会发生报错,提示诸如:ReferenceError: addItem is not defined at HTMLInputElement.onclick的错误
  • 点击中间文本框的时候,我们需要触发事件,那么我们就需要给这个文本框添加change事件,从而实现实时监听,当我们修改完毕之后,点击除了文本框的任意位置,就会触发事件了,我们可以通过alert来进行验证这个触发事件
  • CartServlet中利用cartList来实现对商品的操作的时候,注意的是,cartList是通过session来取得的,而不是我们直接再CartServlet中直接新建得到的如果是我们再CartServlet中新建CartList的话,那么就会导致我们并不是在当前的session的购物车中进行操作的,那么重定向之后,再来点击购物车的时候,就会发现购物车的商品一直是0,所以不会显示数据。因此我们需要保证每次操作都是在session中的cartList操作的,那么就需要每次都需要从session中获取cartList
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:39:00  更:2022-05-11 16:40:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:46:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码