美文网首页
Express+Jquery实现购物车的前后端

Express+Jquery实现购物车的前后端

作者: alicemum | 来源:发表于2021-03-03 11:43 被阅读0次

    需求分析:

    列表页list.html

    html结构

     <p class="login-txt">登录</p>
        <p> <a href="register.html">注册</a></p>
        <p><a href="./shopCart.html">购物车</a></p>
        <div id="box">
            <ul>
               
            </ul>
        </div>
        <div class="mask">
            <div class="login">
                <p><input type="text" class="user"/></p>
                <p><input type="text" class="pw"/></p>
                <p><button>登录</button>></p>
            </div>
        </div>
        <script src="js/axios.js"></script>
        <script src="js/jquery.js"></script>
        <script src="js/jquery.cookie.js"></script>
        <script src="js/list.js"></script>
        <script src="js/addCart.js"></script>
        <script src="js/login.js"></script>
    
    列表页功能一: 初始化展示商品列表

    前端代码

    let page = 1;  //页码
    let mask = document.querySelector(".mask") //获取dom
    
    // 渲染数据
    function render(data) {
        if (data.code === 0) {
            let html = ''
            data.list.forEach((item) => {
                html += `
                <li>
                    <a href="./detail.html?id=${item.Id}">
                        <div class="pro_img"><img src="https:${item.imgUrl}" width="150" height="150"></div>
                        <h3 class="pro_name"><a href="#"> ${item.title} </a></h3>
                        <p class="pro_price">${item.price}元</p>
                        <p></p>
                        <div class="add_btn" data-id="${item.Id}">加入购物车</div>
                    </a>
                </li>
                `
            })
            $("#box ul").append(html)
        }
    }
    // 初始化加载数据
    function initData() {
        axios.get("/product",{
            params: {
                page
            }
        })
        .then((res) => {
            render(res.data)
        })
    }
    
    initData()
    

    后端代码

    // 查询所有商品(分页显示)
    router.get("/product", (req, res) => {
        let { page } = req.query;
        const pageSize = 10;
        let start = (page - 1) * pageSize
        let sql = `select * from midata order by Id asc limit ?,?`
        conn.query(sql, [start, pageSize], function (err, result) {
            if (err) {
                console.log('查询数据库失败');
            } else {
                let data;
                if (result.length) {
                    data = {
                        code: 0,
                        list: result
                    }
                } else {
                    data = {
                        code: 1,
                        msg: '没有结果 '
                    }
                }
                res.send(data)
            }
        })
    })
    
    列表页功能二: 登录入口,可在本页面显示登录窗口,实现登录功能
    // 每个页面中的登录
    function login() {
        $(".mask button").on("click", function () {
            let data = {
                user: $(".user").val(),
                pw: $(".pw").val()
            }
            axios.post('/login', data)
                .then((res) => {
                    console.log(res.data);
                    mask.classList.remove("active")
                    $.cookie("user",data.user,{ expires: 100})
                })
        })
    
    }
    //登录弹窗
    function loginBox() {
        let loginTxt = document.querySelector(".login-txt")
        var login = document.querySelector(".login")
    
        //绑定事件,单击登录时,显示弹窗
        loginTxt.onclick = function () {
            mask.classList.add("active")
        }
    
        //单击遮罩层,让遮罩层消失
        mask.onclick = function () {
            this.classList.remove("active")
        }
    
        //阻止冒泡
        login.onclick = function (e) {
            e.stopPropagation()
        }
    }
    login()
    loginBox()
    
    列表页功能三: 每个商品实现加入购物车功能

    先验证是否登录,如何没有登录,进行登录,如果已登录,则把商品id和用户id传向后端接口

    前端代码

    function cart() {
        // 加入购物车
        function addCart() {
            $("#box ul").on("click", ".add_btn", function () {
                //验证用户是否登录
                let userId = $.cookie("user");
                let proId = $(this).data("id")  //获取商品Id
                console.log(proId);
                if (!userId) {
                    //当cookie不存在,即没有登录
                    mask.classList.add("active")
                    return;
                }
                let data = {
                    userId,
                    proId
                }
                axios.post("/cart",data)
                .then((res)=>{
                    console.log(res.data);
                })
            })
    
        }
        addCart();
    }
    cart()
    

    后端代码

    // 添加商品到购物车
    router.post("/cart", (req, res) => {
        //接收参数
        let { userId, proId } = req.body;
        let sql = "select * from cart where userId = ? and proId = ?"
        conn.query(sql, [userId, proId], function (err, result) {
            if (err) {
                console.log('数据库访问失败');
            } else {
    
                let data;
                if (result.length) {
                    console.log('11');
                    //当前用户存在该商品
                    let cartId = result[0].cartId
                    let num = result[0].num + 1
                    // 更新商品数量 
                    let sql = "update cart set num = ? where cartId = ?"
                    conn.query(sql, [num, cartId], function (err, result) {
                        if (result.affectedRows === 1) {
                            res.send({
                                code: 0,
                                msg: '添加购物车成功,数量更改'
                            })
                        }
                    })
                } else {
                    console.log(22);
                    //当前用户不存在该商品
                    let sql = "insert into cart (userId,proId,num) values (?,?,?)"
                    conn.query(sql, [userId, proId, 1], function (err, result) {
                        if (result.affectedRows === 1) {
                            res.send({
                                code: 0,
                                msg: '添加购物车成功,数量初始为1'
                            })
                        }
                    })
                }
            }
        })
    })
    
    列表页功能四: 加入购物车

    后端接口接收商品id和用户id,先验证该用户的当前商品是否存在,如果不存在,则新增,如果存在,则修改数量

    前端代码

    function cart() {
        // 加入购物车
        function addCart() {
            $("#box ul").on("click", ".add_btn", function () {
                //验证用户是否登录
                let userId = $.cookie("user");
                let proId = $(this).data("id")  //获取商品Id
                console.log(proId);
                if (!userId) {
                    //当cookie不存在,即没有登录
                    mask.classList.add("active")
                    return;
                }
                let data = {
                    userId,
                    proId
                }
                axios.post("/cart",data)
                .then((res)=>{
                    console.log(res.data);
                })
            })
    
        }
        addCart();
    }
    cart()
    
    

    后端代码

    // 添加商品到购物车
    router.post("/cart", (req, res) => {
        //接收参数
        let { userId, proId } = req.body;
        let sql = "select * from cart where userId = ? and proId = ?"
        conn.query(sql, [userId, proId], function (err, result) {
            if (err) {
                console.log('数据库访问失败');
            } else {
    
                let data;
                if (result.length) {
                    console.log('11');
                    //当前用户存在该商品
                    let cartId = result[0].cartId
                    let num = result[0].num + 1
                    // 更新商品数量 
                    let sql = "update cart set num = ? where cartId = ?"
                    conn.query(sql, [num, cartId], function (err, result) {
                        if (result.affectedRows === 1) {
                            res.send({
                                code: 0,
                                msg: '添加购物车成功,数量更改'
                            })
                        }
                    })
                } else {
                    console.log(22);
                    //当前用户不存在该商品
                    let sql = "insert into cart (userId,proId,num) values (?,?,?)"
                    conn.query(sql, [userId, proId, 1], function (err, result) {
                        if (result.affectedRows === 1) {
                            res.send({
                                code: 0,
                                msg: '添加购物车成功,数量初始为1'
                            })
                        }
                    })
                }
            }
        })
    })
    
    列表页功能五: 跳转至详情页

    单击商品,跳转到详情页,并传递当前商品id

    前端代码

    <a href="./detail.html?id=${item.Id}">商品</a>
    

    详情页: detail.html

    详情页功能一: 初始化获取商品id, 请求后端接口,获取商品信息并渲染

    前端代码

    // 获取Id
    function getId(){
        let search = location.search; // "?id=100"
        let result = search.match(/^\?id=(\d+)$/)
        let id = result[1];
        return id
    }
    //渲染数据
    function render(res){
        if (res.data.code === 0) {
            let item = res.data.list[0]
            let html = ''
            html += `
            <li>
                <a href="./detail.html?id=${item.Id}">
                    <div class="pro_img"><img src="https:${item.imgUrl}" width="150" height="150"></div>
                    <h3 class="pro_name"><a href="#"> ${item.title} </a></h3>
                    <p class="pro_price">${item.hot}元</p>
                    <div class="add_btn" data-id="${item.Id}">加入购物车</div>
                </a>
            </li>
            `
            $("#box ul").append(html)
        }
    }
    //获取指定id对应的商品信息
    function getProduct() {
        let id = getId()
        axios.get(`/product/${id}`)
            .then((res) => {
                render(res)
            })
    }
    getProduct()
    

    后端代码

    router.get("/product/:id", (req, res) => {
        let { id } = req.params;
        let sql = `select * from midata where id = ?`
        conn.query(sql, [id], function (err, result) {
            if (err) {
                console.log('查询数据库失败');
            } else {
                let data;
                if (result.length) {
                    data = {
                        code: 0,
                        list: result
                    }
                } else {
                    data = {
                        code: 1,
                        msg: '没有结果 '
                    }
                }
                res.send(data)
            }
        })
    })
    
    详情页功能二: 加入购物车功能,逻辑参考列表页功能

    购物车 shopCart.html

    购物车功能一: 初始化请求后台接口,并传递当前用户id, 请求该用户的所有购物信息并展示

    前端代码

    // 查看用户是否登录
    function checkIsLogin(userId) {
        if (!userId) return;
        //登录过
        $("h1").addClass("hide")
        $(".car").removeClass("hide")
    }
    //渲染数据
    function render(res) {
        if (res.data.code == 0) {
            let html = ""
            res.data.list.forEach((item) => {
                html += `
            <div class="row hid">
            <div class="check left"> <input type="checkbox" class="select"></div>
            <div class="img left"><img src="img/03-car-02.png" width="80" height="80"></div>
            <div class="name left"><span> ${item.title} </span></div>
            <div class="price left"><span>${item.price}元</span></div>
            <div class="item_count_i">
                <div class="num_count">
                    <div class="count_d" data-id="${item.cartId}">-</div>
                    <div class="c_num">${item.num}</div>
                    <div class="count_i" data-id="${item.cartId}">+</div>
                </div>
            </div>
            <div class="subtotal left"><span>${item.price * item.num}元</span></div>
            <div class="ctrl left"><a href="javascript:;" data-id="${item.cartId}">×</a></div>
        </div>
            `
            })
            $(".list").html(html)
        }
    }
    // 请求购物车列表数据
    function loadData() {
        let userId = $.cookie("user")
        checkIsLogin(userId)
        // 请求数据
        axios.get("/cart", {
            params: {
                userId
            }
        })
            .then((res) => {
                render(res)
            })
    
    }
    

    后端代码

    //查询购物车信息
    router.get("/cart", (req, res) => {
        let { userId } = req.query;
        let sql = `select * from cart,midata where cart.userId = ? and cart.proId = midata.Id order by cart.cartId desc`
        conn.query(sql, [userId], function (err, result) {
            if (err) {
                console.log('查询数据库失败');
            } else {
                let data;
                if (result.length) {
                    data = {
                        code: 0,
                        list: result
                    }
                } else {
                    data = {
                        code: 1,
                        msg: '没有结果 '
                    }
                }
                res.send(data)
            }
        })
    })
    
    
    购物车功能二: 复选框全选的单击事件: 选中时,所有商品也要选中,取消选择时,所有商品也取消选择. 同时计算总价

    计算总价

    let total = 0;  //总价
    //计算总价
    function getTotal() {
        total = 0;
        [...$(".list .select")].forEach((item) => {
            if ($(item).prop("checked")) {
                let subTotal = parseFloat($(item).parent().parent().find(".subtotal span").text())
                total += subTotal
            }
        })
        $("#sum_area #price_num").text(total)
    }
    

    前端代码

    // 全选功能
    function checkAll() {
        $(".check-all").on("click", function () {
            let selected = $(this).prop("checked")
            $(".list .select").prop("checked", selected)
            getTotal()
        })
    }
    
    购物车功能三. 每个商品复选框的单击事件: 单击时,要遍历所有商品的选中状态,都被选中,则选中“全选”复选框,都取消选中,则取消“全选”复选框。 同时计算总价

    前端代码

    //切换某一个商品的选择状态
    function toggleOne() {
        $(".list").on("click", ".select", function () {
            let selected = $(this).prop("checked")
            if (selected) {
                let flag = [...$(".list .select")].every((item) => {
                    return $(item).prop("checked")
                })
                if (flag) {
                    $(".check-all").prop("checked", true)
                }
            } else {
                $(".check-all").prop("checked", false)
            }
            getTotal()
        })
    }
    
    购物车功能四. 加减数量: 获取原有数量,加或减后,调用后端接口,传递数量,CartId, 后端则把对应购物车信息的数量进行更新。 前端接收到更新成功后,计算小计价格,并同时计算总价

    前端代码

    //改变数量
    function changeNum(el, type) {
        $(".list").on("click", el, function () {
            let num = $(this).siblings(".c_num").text()
            type === 'add' ? num++ : num--
            //后端接口
            let data = {
                cartId: $(this).data("id"),
                num
            }
            axios.put("/cart", data)
                .then((res) => {
                    //前端 
                    $(this).parent().parent().siblings(".check").children(".select").prop("checked", true);
                    let price = parseFloat($(this).parent().parent().siblings(".price").children("span").text())
                    $(this).siblings(".c_num").text(num)
                    let subTotal = num * price
                    $(this).parent().parent().siblings(".subtotal").children("span").text(subTotal)
                    getTotal()
                })
        })
    }
    

    后端代码

    //修改商品数量
    router.put("/cart", (req, res) => {
        //接收参数
        let { cartId, num } = req.body;
        let sql = "update cart set num = ? where cartId = ?"
        conn.query(sql, [num, cartId], function (err, result) {
            if (err) {
                console.log('数据库访问失败');
            } else {
                if (result.affectedRows === 1) {
                    res.send({
                        code: 0,
                        msg: '添加购物车成功,数量更改'
                    })
                }
            }
        })
    })
    
    购物车功能五: 删除: 调用后端接口,传递CartId, 在后端删除指定CartId的信息,前端接收到成功删除后,再次到后端请求当前用户所有购物车信息并渲染

    前端代码

    // 删除购物车信息
    function delCart() {
        $(".list").on("click", ".ctrl a", function () {
            let cartId = $(this).data("id")
            axios.delete(`/cart/${cartId}`)
                .then((res) => {
                    loadData()
                })
        })
    }
    

    后端代码

    //删除购物车信息
    router.delete("/cart/:cartId", (req, res) => {
        let { cartId } = req.params;
        let sql = `delete from cart where cartId = ?`
        conn.query(sql, [cartId], function (err, result) {
            if (err) {
                console.log('查询数据库失败');
            } else {
                let data;
                if (result.affectedRows === 1) {
                    data = {
                        code: 0,
                        msg: '删除成功'
                    }
                }
                res.send(data)
            }
        })
    })
    

    相关文章

      网友评论

          本文标题:Express+Jquery实现购物车的前后端

          本文链接:https://www.haomeiwen.com/subject/zikqqltx.html