Vue + jQuery学习案例【购物车订单管理】

一、题目要求

题目要求:
1.作出如图的展示效果
2.点击购买加号则数量增加,总价格随之更变
3.如果书本数量为1则不能减少
4.点击移除,删除该行,总价格随之更变
5.使用VUE + HTML 实现该案例在这里插入图片描述说明:
题目中没有要求实现添加订单的功能,添加订单的实现是我自己想练手,所以添加了这个模块,当然实际开发中不可能是这种手动输入来添加订单的方式,我这里的实现纯粹是用于学习(用原生HTML和jQuery实现布局和交互效果),没有刻意引入UI框架。不喜勿喷喔

二、效果演示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、完整代码

1、shopping-cart.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>购物车案例</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="./jquery-3.5.1.js"></script>
    <link rel="stylesheet" href="./shopping-cart.css">
</head>

<body>
    <!-- 
        1、页面布局
        2、添加数量功能
        3、减少数量功能
        4、删除书籍功能
        5、总价计算更新功能
        6、添加订单功能
            6.1 校验信息功能
            6.2 取消添加功能
            6.3 确认添加功能
     -->
    <div id="app">
        <div v-show="isShowOrderDiv">
            <table class="order">
                <caption>
                    <h1>购物车清单管理</h1>
                </caption>
                <tr class="options">
                    <td colspan="6">
                        <span class="add" @click="openAdd"></span>
                    </td>
                </tr>
                <tr>
                    <th scope="col" class="num"></th>
                    <th scope="col" class="book_name">书籍名称</th>
                    <th scope="col" class="publish_date">出版日期</th>
                    <th scope="col" class="book_price">价格</th>
                    <th scope="col" class="buy_count">购买数量</th>
                    <th scope="col" class="action">操作</th>
                </tr>

                <tr class="th" v-for="(book,index) in book_list">
                    <td class="num">{{book.num}}</td>
                    <td class="book_name">《{{book.book_name}}》</td>
                    <td class="publish_date">{{book.publish_date}}</td>
                    <td class="book_price">¥{{book.book_price}}</td>
                    <td class="buy_count">
                        <span class="minus" v-bind:class="[book.isMore?'more':'one']"
                            @click="[book.buy_count > 1 ? minusCount(index):'']">-</span>
                        <span class="count_value">{{book.buy_count}}</span>
                        <span class="plus more" @click="addCount(index)">+</span>
                    </td>
                    <td class="action">
                        <span class="delete" @click="deleteBook(index)">
                            <svg t="1609162597621" class="icon" viewBox="0 0 1024 1024" version="1.1"
                                xmlns="http://www.w3.org/2000/svg" p-id="2030" width="20" height="20">
                                <path
                                    d="M677.35552 204.8l0-61.44c0-33.91488-29.61408-61.44-66.1504-61.44l-198.49216 0c-36.57728 0-66.19136 27.52512-66.19136 61.44l0 61.44-264.64256 0 0 61.44 99.24608 0 0 614.4c0 33.95584 29.65504 61.44 66.1504 61.44l529.32608 0c36.57728 0 66.19136-27.48416 66.19136-61.44l0-614.4 99.24608 0 0-61.44L677.35552 204.8 677.35552 204.8zM412.71296 143.36l198.49216 0 0 61.44-198.49216 0L412.71296 143.36 412.71296 143.36zM776.6016 880.64 247.27552 880.64l0-614.4 529.32608 0L776.6016 880.64 776.6016 880.64zM346.5216 358.4l66.19136 0 0 430.08-66.19136 0L346.5216 358.4 346.5216 358.4zM478.86336 358.4l66.1504 0 0 430.08-66.1504 0L478.86336 358.4 478.86336 358.4zM611.20512 358.4l66.1504 0 0 430.08-66.1504 0L611.20512 358.4 611.20512 358.4zM611.20512 358.4"
                                    p-id="2031"></path>
                            </svg>
                        </span>
                    </td>
                </tr>

            </table>
            <p class="sum_price">总价格:¥<span>{{sum_price}}</span></p>
        </div>
        <div v-show="isShowAddDiv" id="add-wrapper">
            <table>
                <span class="titlebar">添加订单</span>
                <tr scope="col">
                    <td>
                        <label for="book_name"><span style="color: red;">*</span>书名:</label>
                    </td>
                    <td>
                        <input type="text" id="book_name">
                    </td>
                </tr>
                <tr scope="col">
                    <td>
                        <label for="publish_date"><span style="color: red;">*</span>出版日期:</label>
                    </td>
                    <td>
                        <input type="text" id="publish_date">
                    </td>
                </tr>
                <tr scope="col">
                    <td>
                        <label for="book_price"><span style="color: red;">*</span>价格:</label>
                    </td>
                    <td>
                        <input type="text" id="book_price">
                    </td>
                </tr>
                <tr scope="col">
                    <td>
                        <label for="buy_count"><span style="color: red;">*</span>购买数量:</label>
                    </td>
                    <td>
                        <input type="text" id="buy_count">
                    </td>
                </tr>
                <tr style="color: red;height:30px;line-height: 30px; text-align: right;padding-right: 20px;">
                    <td colspan="2">{{warn_info}}</td>
                </tr>
            </table>
            <div class="btnDiv">
                <span id="cancelAddBtn" @click="cancelAdd">×</span>
                <span id="confirmAddBtn" @click="addBook"></span>
            </div>
        </div>
    </div>
</body>
<script>
    new Vue({
        el: "#app",
        data: {
            sum_price: 0,
            book_num: 0,
            book_list: [],
            isShowOrderDiv: true,     //默认展示订单页面
            isShowAddDiv: false,      //默认不展示添加页面
            warn_info: ""             //警告信息
        },
        methods: {
            addCount(index) {
                //vue的forEach循环
                var list = this.book_list;
                list.forEach((item, i) => {
                    if (index == i) {
                        //将减少按钮置为可点击样式
                        if (item.buy_count == 1) {
                            item.isMore = true
                        }
                        //将购买数量+1
                        item.buy_count += 1;
                        //将总价格更新
                        this.sum_price = this.roundFun(this.sum_price + item.book_price)
                    }
                })
                this.book_list = list;
            },
            minusCount(index) {
                //vue的forEach循环
                var list = this.book_list;
                list.forEach((item, i) => {
                    if (index == i) {
                        //将购买数量-1
                        item.buy_count -= 1;
                        //将减少按钮置为可点击样式
                        if (item.buy_count == 1) {
                            item.isMore = false
                        }
                        //将总价格更新
                        this.sum_price = this.roundFun(this.sum_price - item.book_price)
                    }
                })
                this.book_list = list;
            },
            //删除订单记录的方法
            deleteBook(index) {
                //将book从book_list中移除
                let list = this.book_list.filter((item, i) => {
                    if (index == i) {
                        //将总价更新
                        this.sum_price = this.roundFun(this.sum_price - item.book_price * item.buy_count);
                        //将总订单数更新
                        this.book_num -= item.buy_count
                    }
                    return index != i
                })
                //将删除后的数组序号更新
                list.forEach((item, i) => {
                    item.num = i + 1
                })

                this.book_list = list
            },
            //打开添加订单页面
            openAdd() {
                this.isShowOrderDiv = false;
                this.isShowAddDiv = true;
            },
            //添加订单的方法
            addBook() {
                this.warn_info = ""
                let book_name = $("#book_name").val();
                let publihs_date = $("#publish_date").val();
                let book_price = $("#book_price").val();
                let buy_count = $("#buy_count").val();
                if (book_name === "" || publihs_date === "" || book_price === "" || buy_count === "") {
                    this.warn_info = "必填项不允许空值!"
                    return
                }
                //校验发布日期是否符合日期规范
                if (this.isFormatDate(publihs_date) === false) {
                    this.warn_info = "日期应为yyyy-mm-dd或者yyyy/mm/dd的格式!"
                    return
                }
                //校验书籍价格是否为非负数字
                if (this.isPrice(book_price) === false) {
                    this.warn_info = "价格应该为正数,且最多包含2位小数!"
                    return
                }
                //校验购买数量是否为正整数
                if (this.isBuyCount(buy_count) === false) {
                    this.warn_info = "购买数量应该为正整数!"
                    return
                }

                //创建一个JSON对象存储新的书籍信息
                let book = {
                    num: this.book_num + 1,
                    book_name: book_name,
                    publish_date: publihs_date.replaceAll("/", "-"),
                    book_price: parseFloat(book_price),
                    buy_count: parseInt(buy_count),
                    isMore: buy_count > 1 ? true : false
                }

                //将book添加到book_list中
                this.book_list.push(book)

                //将总价更新
                this.sum_price = this.roundFun(this.sum_price + book.book_price * book.buy_count);
                //将总订单数更新
                this.book_num += 1

                //关闭添加订单页面,展示订单列表页面,关闭警告信息提示
                this.isShowOrderDiv = true;
                this.isShowAddDiv = false;
                this.initInput();
                this.warn_info = "";
            },
            //取消添加订单的方法
            cancelAdd() {
                this.isShowOrderDiv = true;
                this.isShowAddDiv = false;
                this.initInput();
            },
            //清空输入框
            initInput() {
                this.warn_info = "";
                $("#book_name").val("");
                $("#publish_date").val("");
                $("#book_price").val("");
                $("#buy_count").val("");
            },
            //价格是否为正数,且最多有2位小数
            isPrice(val) {
                var regPos = /^\d+(\.\d{1,2})?$/; //非负整数,或者有1-2位小数
                if (regPos.test(val)) {
                    return true;
                } return false;
            },
            //日期是否符合日期规范yyyy-mm-dd或者yyyy/mm/dd格式
            isFormatDate(val) {
                var reg = /^\d{4}(-|\/)\d{2}(-|\/)\d{2}$/;
                if (reg.test(val)) {
                    return true;
                } return false;
            },
            //购买数量是否为正整数
            isBuyCount(val) {
                var reg = /^[1-9]{1}(\d*)$/;  //第一位必须为1-9,后面的数可以为0-n个任意数字
                if (reg.test(val)) {
                    return true;
                } return false;
            },
            //保留俩位小数
            roundFun(value, n = 2) {
                return Math.round(value * Math.pow(10, n)) / Math.pow(10, n);
            }

        }
    });
</script>

</html>

2、shopping-cart.css

#app{
    margin:auto;
    width:850px;
}
table.order h1{
    color:burlywood;
}
table.order{
    border-collapse: collapse;
    border-spacing: 0px;
}
table.order td,th{
    border:1px solid #ccc;
    text-align: center;
    font-family: 'STHeiTi';
}
table.order tr{
    height:40px;
}
table.order tr:first-child td{
    border: none;
    text-align: left;
}
table.order th{
    background-color:whitesmoke;
    font-weight: bold;
    color:grey;
}
.num{
    width:50px;
}
.book_name{
    width:300px;
}
.publish_date{
    width:130px;
}
.book_price{
    width:120px;
}
.buy_count{
    width:200px;
}
.action{
    width:100px;
}
.one,.more{
    display: inline-block;
    width:20px;
    height:20px;
    line-height: 20px;
    text-align: center;
    border: 1px solid;
}
.one{
    color:grey;
    border-color:gainsboro;
}
.more{
    color:black;
    cursor:pointer;
}
.count_value{
    display:inline-block;
    width:50px;
    height:20px;
    line-height: 20px;
    text-align: center;
    border:0px;
    outline: none; 
}
.delete,.options .add{
    display: inline-block;
    height:30px;
    border-radius: 5px;
    line-height: 30px;
    cursor:pointer;
    color:white;
}
.delete{
    width:50px;
    background-color: red;
}
.options .add{
    font-weight: bold;
    width:60px;
    background-color: deepskyblue;
    text-align: center;
}

.options td{
    text-align: left;
    
}
table.order span>svg{
    margin:auto;
    margin-top:5px;
    fill:currentColor;
    color:white;
}
.sum_price{
    text-align: right;
    font-weight: bold;
    font-size: 20px;
}

/*设置添加订单div的样式*/
#add-wrapper{
    width:500px;
    margin:100px auto;
    height:370px;
    /* border:1px solid grey; */
    box-shadow:#ccc 5px 5px 5px 5px;
    position: relative;
}
#add-wrapper span.titlebar{
    display: inline-block;
    width:500px;
    height:50px;
    line-height: 50px;
    text-align: center;
    background-color: deepskyblue;
    color: white;
    font-size: 20px;
    font-weight: bold;
}
#add-wrapper tr{
    width:400px;
}
/* #add-wrapper span{
    display: block;
    width:80px;
    height:30px;
    margin-top:10px;
} */
#add-wrapper table{
    padding: 50px 50px 0px 50px;
}
#add-wrapper tr{
    height: 40px;
    line-height: 40px;
}
/* #add-wrapper td{
    border:1px solid red;
} */
#add-wrapper tr td label{
    display: inline-block;
    width:100px;
    text-align: right;
}
#add-wrapper tr td input{
    height:30px;
    width:230px;
    line-height: 30px;
    font-size: 15px;
}
/* #add-wrapper table tr:last-child{
    margin-top:50px;
    text-align: right;
} */
.btnDiv{
    width:100%;
    height:50px;
    float: left;
    position: relative;
    top:20px;
    right:20px;
    text-align: right;
}
#confirmAddBtn{
    display: inline-block;
    height:30px;
    width:30px;
    border-radius: 50%;
    line-height: 30px;
    cursor:pointer;
    color:white;
    background-color: deepskyblue;
    text-align: center;
    font-weight: bold;
    font-size: 20px;
}
#cancelAddBtn{
    display: inline-block;
    height:30px;
    width:30px;
    border-radius: 50%;
    line-height: 30px;
    cursor:pointer;
    color:white;
    background-color:crimson;
    text-align: center;
    font-weight: bold;
    font-size: 20px;
    margin-right: 10px;
}

四、问题总结

1、取消table第一行的外边框不生效

  • 取消table第一行的外边框,希望达到下方的效果
    在这里插入图片描述
    但是发现始终不生效,最后一点点清除代码验证效果后,发现是body中table标签多写了一个border="1“的属性,同时tr:first-child后面的td也老是忘加,导致一直不生效

  • 这是不生效的效果图:在这里插入图片描述

  • 错误代码如下:
    在这里插入图片描述

相关参考: 怎样写HTML,把表格的第一行的边框去掉,该怎么解决

2、总价格的小数点超过2位也会展示

  • 最开始在计算和更新总价格的时候,使用的是-=、+=运算符,但是后续测试中发现:当价格与数量乘积超过2位小数时,也会直接展示,所以参考网上方法,将-=、+=运算符改为普通 = 运算符,并且将最终计算的结果精确到了2位小数
  • 参考资料:js保留两位小数的方法

3、H5的table没有cellspacing属性

  • 因为H5中取消了一些属性,代替的是使用CSS实现,其中就包括cellspacing属性
  • 解决方法:
table{
	border-collapse: collapse;
    border-spacing: 0px;
}

4、实现div的显示与隐藏效果

  • 因为没有引入市面的UI框架,比如elementUI等,所以就得自己实现div的显示与隐藏
  • 这里采用的是vue的v-show属性,用于控制标签是否展示,值需要在vue对象的data中给出
  • 示例:
    html代码
    在这里插入图片描述
    vue代码:
    在这里插入图片描述

5、日期、价格、数量的格式校验

  • 因为本身这个案例只是用来学习,实际情况不会出现订单需要手动输入的情况,所以这里的校验只是对数据格式进行校验,并没有对数据内容进行严格的控制
  • 采用的是js的正则表达式进行字符串校验
  • 价格后续要进行计算,最后用parseFloat方法转为float类型
  • 数量也要进行计算,最后用parseInt方法转为int类型

6、如何处理每一个订单信息

  • 起初我没太想明白如何处理每一个订单信息,也是因为基础不扎实,最开始尝试使用生成tr标签的方式去添加订单信息
  • 后来意识到行不通,回想了一下学习的课程中老师讲的知识点,确定了要使用v-for属性
  • 使用v-for也就必须要提供一个数组,然后就想到,每一个订单信息,都可以当成一个JSON对象,依次存入到一个数组中,然后v-for进行遍历取出每一条订单信息进行展示
  • 当然,html中要写好展示订单信息的模板,如下:
    在这里插入图片描述

7、如何传递指定的一条记录进行删除操作

  • 最开始,没考虑将每一条订单信息当作一个JSON对象处理,然后就一直想着用this对象去修改数据
  • 但是因为一个HTML中只创建了一个Vue对象,this对象的值只能从vue的data中取,也就意味着如果要用this对象来直接处理数据,一个vue对象,只能保存一条订单的信息,这样多条订单就很难实现了。
  • 后来采用数组存放订单对象的方式实现,然后顺其自然就想到了索引。
  • 根据数组的索引进行修改数组中指定索引对象的属性值,相比之前的思路,这种方案才有较好的可行性
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
图书管理系统是一个常见的项目,下面是使用 SpringBoot + MyBatisPlus + Restful + Vue + Jquery + Axios 的图书管理系统的简单介绍。 1. 项目概述 该项目是一个图书管理系统,主要功能包括: - 图书的增删改查 - 图书分类的增删改查 - 图书借阅的管理 2. 技术栈 - 后端:SpringBoot + MyBatisPlus + Restful - 前端:Vue + Jquery + Axios 3. 功能模块 - 登录模块:用户登录、退出登录 - 图书管理模块:图书查询、添加、修改、删除 - 图书分类模块:图书分类查询、添加、修改、删除 - 借阅管理模块:借阅记录查询、添加、修改、删除 4. 项目结构 - backend:后端代码 - src/main/java/com/example/demo:Java 代码 - src/main/resources:配置文件和静态资源 - frontend:前端代码 - src:Vue 代码 5. 实现步骤 - 使用 Spring Initializr 创建一个 SpringBoot 项目 - 引入 MyBatisPlus、Druid 数据库连接池、Lombok 等依赖 - 创建数据库表,使用 MyBatisPlus 自动生成实体类和 Mapper 接口 - 创建 Restful API,提供图书、图书分类、借阅记录的增删改查接口 - 使用 VueJquery、Axios 等前端技术实现前端界面,调用后端提供的接口实现相应功能 6. 总结 该项目基于 SpringBoot + MyBatisPlus + Restful + Vue + Jquery + Axios 技术栈,实现了一个简单的图书管理系统。通过该项目,可以学习到如何使用 SpringBoot 进行开发,如何使用 MyBatisPlus 简化数据库操作,以及如何使用 VueJquery、Axios 等前端技术实现前端界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迟到_啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值