Vue实现手机端界面的购物车案例

news2024/9/22 21:15:17

目录

前期准备

Header

Goods

Counter


今天用Vue实现的一个手机端的购物车案例,着重阐述组件化思想的优势,将页面的内容分成各个模块进行书写,然后数据传输,父传子、子传父、兄弟数据共享等,这方面知识不牢固的话可以关注一下右方vue的专栏:Vue专栏 里面详解介绍了vue的知识,今天的案例也是借助黑马的相关案例及其接口,既是分享也是回顾。

前期准备

因为本案例是借助vue的框架进行实现的,所以我们需要先搭建vue-cli脚手架,具体的搭建过程请看右方链接  vue-cli脚手架的搭建与使用 ,搭建完成后,需要根据案例的具体的图片功能点要求给components文件下新建子组件文件,案例实现结果以及父子组件的框架如下:

写项目之前先选择好自己想要的手机版本是什么,我这里就用最常见的iPhone 6/7/8 这个手机尺寸了,如果想更换手机版本,可以自行在浏览器进行更换。

为了语义化,这边我把components文件名更改为shopping,不该也没关系。

根据上文图片案例,我们先从上面也是最简单的Header来写,为了便于数据的管理,我们把标题设置为自定义属性,允许使用者自定义标题的内容。

Header.vue子组件代码

<template>
  <div class="header-container">{{title}}</div>
</template>
<script>
export default {
    props:{
        // 声明 title 自定义属性,允许使用者自定义标题的内容
        title:{
            default:'',
            type:String
        }
    }
}
</script>
<style lang="less" scoped>
    .header-container{
        font-size: 12px;
        height: 45px;
        width: 100%;
        background-color: #008c8c;
        display: flex;
        justify-content: center;
        align-items: center;
        color: #fff;
        position: fixed;
        top: 0;
        z-index: 999;
    }
</style>

App.vue父组件代码

<template>
  <div class="app-container">
    <!-- 头部区域 -->
    <Header title="购物车案例"></Header>
  </div>
</template>
<script>
  // 导入需要的组件
  import Header from '@/shopping/Header/Header.vue'
  export default {
    components:{
      Header
    }
  }
</script>
<style lang="less" scoped>
  .app-container{
    padding-top: 45px;
    padding-bottom:50px
  }
</style>

Goods

现在开始从项目的内容入手,因为子组件的内容肯定不能写死了,所以需要将父组件的值传入到子组件,而父组件的值从哪来?这里需要借助接口来获取自己要渲染的商品列表数据,而借助接口传值需要使用ajax或者是axios,所以我们需要先在当前项目下安装 axios,命令如下:

npm install axios -S

安装完成之后,在App.vue 父组件下 使用axios调用接口进行使用:很明显,我们先在data里面定义一个空数组,如果接收到接口里面的数据状态为200,就把接口里面的数据传递到我们定义的list里面,具体方法如下:

在控制台打印的接口数据如下,可以方便的查看接口里面的属性:

Goods.vue子组件代码

因为子组件的复选框的数据是没有和父组件的数据进行联通的,如果不把子组件修改复选框的状态的值传到App.vue父组件上,父组件上的goods_state是不会发生变化的,所以要通过自定义事件进行子向父传值,将复选框的修改状态传递到父组件上面。

<template>
    <div class="goods-container">
        <!-- 左侧图片 -->
        <div class="thumb">
            <!-- 复选框 -->
            <div class="custom-control custom-checkbox">
                <input type="checkbox" class="custom-control-input" :id="'cb'+id" :checked="state" @change="stateChange" />
                <label :for="'cb'+id" class="custom-control-label">
                <!-- 商品的缩略图 -->
                <img :src="pic" alt="">
                </label>
            </div>
        </div>
        <!-- 右侧信息区域 -->
        <div class="goods-infos">
            <!-- 商品标题 -->
            <h6 class="goods-title">{{title}}</h6>
            <div class="goods-info-bottom">
                <!-- 商品价格 -->
                <span class="goods-price">¥{{price}}</span>
                <!-- 商品的数量 -->
            </div>
        </div>
    </div>
</template>

<script>
export default {
    props:{
        // 商品的id,将来子组件中商品的勾选状态变化之后,需要通过子 -> 父的形式,通知父组件根据id修改对应商品的修改状态
        id:{
            require:true,
            type:Number
        },
        // 要渲染的商品的标题
        title:{
            default:'',
            type:String
        },
        // 要渲染的商品的图片
        pic:{
            default:'',
            type:String
        },
        // 商品的单价
        price:{
            default:0,
            type:Number
        },
        // 商品的勾选状态
        state:{
            default:true,
            type:Boolean
        },
    },
    methods:{
        // 只有复选框的选中状态发生了变化就会调用这个处理函数
        stateChange(e){
            const newState = e.target.checked;
            this.$emit('state-change', {id:this.id,value:newState});
        }
    },
}
</script>

<style lang="less" scoped>
.goods-container{
    + .goods-container{
        border-top:1px solid #efefef
    }

    padding: 10px;
    display: flex;
    .thumb{
        display: flex;/*display:flex 意思是弹性布局,它能够扩展和收缩 flex 容器内的元素,以最大限度地填充可用空间。*/
        align-items: center;/* 设置项目交叉轴方向上的对齐方式 */
        img{
            width: 80px;
            height: 80px;
            margin: 10px;
        }
        .custom-control{
            width: 114px;
            height: 105px;
        }
    }
    .goods-infos{
        display: flex;
        flex-direction: column;/*灵活的项目将垂直显示,正如一个列一样。在这里插入图片描述*/
        justify-content: space-between;/* 均匀排列每个元素首个元素放置于起点,末尾元素放置于终点 */
        height: 100px;
        flex: 1;
        .goods-title{
            font-size: 12px;
            font-weight: bold;
        }
        .goods-info-bottom{
            display: flex;
            justify-content: space-between;
            .goods-price{
                font-weight: bold;
                color: red;
                font-size: 13px;
            }
        }
    }
}
</style>

App.vue父组件代码

父组件通过接收子组件自定义的事件名,通过将函数methods里面的方法判断,来进行动态的改变 list.goods_state 里面的值。

<template>
  <div class="app-container">
    <!-- 头部区域 -->
    <Header title="购物车案例"></Header>
    <!-- 循环渲染每一个商品的信息 -->
    <Goods 
      v-for="item in list"
      :key="item.id"
      :id="item.id" 
      :title="item.goods_name" 
      :pic="item.goods_img" 
      :price="item.goods_price" 
      :state="item.goods_state"
      @state-change="getNewState"
      >
    </Goods>
  </div>
</template>
<script>
  // 导入 axios 请求库
  import axios from 'axios'
  // 导入需要的组件
  import Header from '@/shopping/Header/Header.vue'
  import Goods from '@/shopping/Goods/Goods.vue'
  export default {
    data(){
      return {
        // 用来存储购物车的列表数据,默认为空数组
        list:[]
      }
    },  
    methods:{
      // 封装请求列表数据的方法
      async initCarList(){
        // 调用 axios 的 get 方法,请求列表数据
        const {data:res} =  await axios.get("https://www.escook.cn/api/cart")
        console.log(res);
        if(res.status === 200){
          this.list = res.list 
        }
      },
      // 接收子组件传递过来的数据
      getNewState(val){
        this.list.some(item => {
          if(item.id === val.id){
            item.goods_state = val.value
            // 终止后续循环
            return true
          }
        })
      },
    },
    components:{
      Header,Goods
    },
    created(){
      // 调用请求数据的方法
      this.initCarList()
    }
  }
</script>
<style lang="less" scoped>
  .app-container{
    padding-top: 45px;
    padding-bottom:50px
  }
</style>

现在实现购物车底部的全选、总计、以及结算的功能样式,因为数据也不能写死了,所以需要我们进行数据绑定,然后通过父组件获取的数据进行传值。

Footer.vue子组件代码

<template>
    <div class="footer-container">
        <!-- 左侧的全选 -->
        <div class="custom-control custom-checkbox">
            <input type="checkbox" class="custom-control-input" id="cbFull" :checked="isfull" @change="fullchange">
            <label for="cbFull" class="custom-control-label">全选</label>
        </div>
        <!-- 中间的合计 -->
        <div>
            <span>合计:</span>
            <span class="total-price">¥{{amount.toFixed(2)}}</span>
        </div>
        <!-- 结算按钮 -->
        <button type="button" class="btn btn-primary btn-settle">结算({{all}})</button>
    </div>
</template>

<script>
export default {
    props:{
        // 全选的状态
        isfull:{
            type:Boolean,
            default:true
        },
        // 总价格
        amount:{
            type:Number,
            default:0
        },
        // 已勾选的商品的总数量
        all:{
            type:Number,
            default:0
        }
    },
    methods:{
        // 监听到了全选的状态变化
        fullchange(e){
            this.$emit('full-change',e.target.checked)
        }
    }
}
</script>

<style lang="less" scoped>
    .footer-container{
        font-size: 12px;
        height: 60px;
        width: 100%;
        border-top: 1px solid #efefef;
        position: fixed;
        bottom: 0;
        background-color: #fff;
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0 10px;
        .custom-checkbox{
            font-size: 13px;
            display: flex;
            align-items: center;
            .custom-control-label{
                margin-bottom: -5px;
            }
            #cbFull{
                margin-right: 5px;
            }
        }
        .total-price{
            font-weight: bold;
            font-size: 14px;
            color: red;
        }
        .btn-settle{
            height: 70%;
            min-width: 110px;
            border-radius: 25px;
            font-size: 12px;
        }

    }
</style>

App.vue父组件代码

<template>
  <div class="app-container">
    <!-- 头部区域 -->
    <Header title="购物车案例"></Header>
    <!-- 循环渲染每一个商品的信息 -->
    <Goods 
      v-for="item in list"
      :key="item.id"
      :id="item.id" 
      :title="item.goods_name" 
      :pic="item.goods_img" 
      :price="item.goods_price" 
      :state="item.goods_state"
      @state-change="getNewState"
      >
    </Goods>
    <!-- Footer区域 -->
    <Footer :isfull="fullState" :amount="amt" :all="total" @full-change="getFullState"></Footer>
  </div>
</template>
<script>
  // 导入 axios 请求库
  import axios from 'axios'
  // 导入需要的组件
  import Header from '@/shopping/Header/Header.vue'
  import Goods from '@/shopping/Goods/Goods.vue'
  import Footer from '@/shopping/Footer/Footer.vue'
  export default {
    data(){
      return {
        // 用来存储购物车的列表数据,默认为空数组
        list:[]
      }
    },  
    methods:{
      // 封装请求列表数据的方法
      async initCarList(){
        // 调用 axios 的 get 方法,请求列表数据
        const {data:res} =  await axios.get("https://www.escook.cn/api/cart")
        console.log(res);
        if(res.status === 200){
          this.list = res.list 
        }
      },
      // 接收子组件传递过来的数据
      getNewState(val){
        this.list.some(item => {
          if(item.id === val.id){
            item.goods_state = val.value
            // 终止后续循环
            return true
          }
        })
      },
      // 接收 Footer 子组件传递过来的全选按钮的状态
      getFullState(val){
        this.list.forEach(item => item.goods_state = val)
      }
    },
    computed:{
      // 动态计算出全选的状态是 true 还是 false
      fullState(){
         return this.list.every(item => item.goods_state)
      },
      // 已勾选的商品总价格
      amt(){
        // 1.先filter过滤
        // 2.再reduce累加
        return this.list.filter(item=>item.goods_state).reduce((total,item)=>{
          return total+=item.goods_price * item.goods_count
        },0)
      },
      // 已勾选商品的总数量
      total(){
        return this.list.filter(item => item.goods_state).reduce((t,item)=>{
          return t+=item.goods_count
        },0)
      }
    },
    components:{
      Header,Goods,Footer
    },
    created(){
      // 调用请求数据的方法
      this.initCarList()
    }
  }
</script>
<style lang="less" scoped>
  .app-container{
    padding-top: 45px;
    padding-bottom:50px
  }
</style>

Counter

因为count是修改商品的数量的,所以修改的数量要直接修改到父组件的App.vue里面的数据,而要想直接修改App.vue数据是不可能的,因为Counter组件外面还嵌套一层Goods组件,App与Counter相当于爷孙的关系,所以我们可以通过eventBus让Counter直接去修改App里面的值。

eventBus.js文件

import Vue from 'vue'
export default new Vue()

 Counter.vue子组件

因为Counter是嵌套在Goods组件里面的,所以我们还需要在Goods组件去引用Counter子组件

给Goods的props属性在设置一个count,用来表明商品的数量。

<template>
    <div class="number-container d-flex justify-content-center align-items-center">
        <!-- 减 1 的按钮 -->
        <button type="button" class="btn btn-light bnt-sm" @click="sub">-</button>
        <!-- 购买的数量 -->
        <span class="number-box">{{num}}</span>
        <!-- 加 1 的按钮 -->
        <button type="button" class="btn btn-light bnt-sm" @click="add">+</button>
    </div>
</template>

<script>
// 导入eventBus文件
import bus from '@/shopping/eventBus.js'
export default {
    props:{
        // 接收商品的id值,将来使用 EventBus 方案,把数量传递到 App.vue 的时候,需要通知 App 组件,更新哪个商品的数量
        id:{
            type:Number,
            required:true
        },
        // 接收到的 num 数量值
        num:{
            type:Number,
            default:1
        } 
    },
    methods:{
        // 点击按钮,数值+1
        add(){
            // 要发送给 App 的数据格式为 {id,value}
            // 其中,id是商品的id;value是商品最新的购买数量
            const obj = {id:this.id,value:this.num+1}
            // 要做的事:通过 EventBus 把 obj 对象,发送给 App.vue 组件
            bus.$emit('share',obj)
        },
        sub(){
            if(this.num-1 == 0) return 
            // 要发送给 App 的数据格式为 {id,value}
            // 其中,id是商品的id;value是商品最新的购买数量
            const obj = {id:this.id,value:this.num-1}
            // 要做的事:通过 EventBus 把 obj 对象,发送给 App.vue 组件
            bus.$emit('share',obj)
        }
    }
}
</script>

<style>

</style>

App.vue父组件代码

导入eventBus.js文件,通过bus.$on()方法,调用Counter传来的share里面的数据,通过传来的数据,来修改list里面的goods_count里面的值。

<template>
  <div class="app-container">
    <!-- 头部区域 -->
    <Header title="购物车案例"></Header>
    <!-- 循环渲染每一个商品的信息 -->
    <Goods 
      v-for="item in list"
      :key="item.id"
      :id="item.id" 
      :title="item.goods_name" 
      :pic="item.goods_img" 
      :price="item.goods_price" 
      :state="item.goods_state"
      :count="item.goods_count"
      @state-change="getNewState"
      >
    </Goods>
    <!-- Footer区域 -->
    <Footer :isfull="fullState" :amount="amt" :all="total" @full-change="getFullState"></Footer>
  </div>
</template>
<script>
  // 导入 axios 请求库
  import axios from 'axios'
  // 导入需要的组件
  import Header from '@/shopping/Header/Header.vue'
  import Goods from '@/shopping/Goods/Goods.vue'
  import Footer from '@/shopping/Footer/Footer.vue'
  // 导入eventBus文件
  import bus from '@/shopping/eventBus.js'
  export default {
    data(){
      return {
        // 用来存储购物车的列表数据,默认为空数组
        list:[]
      }
    },  
    methods:{
      // 封装请求列表数据的方法
      async initCarList(){
        // 调用 axios 的 get 方法,请求列表数据
        const {data:res} =  await axios.get("https://www.escook.cn/api/cart")
        console.log(res);
        if(res.status === 200){
          this.list = res.list 
        }
      },
      // 接收子组件传递过来的数据
      getNewState(val){
        this.list.some(item => {
          if(item.id === val.id){
            item.goods_state = val.value
            // 终止后续循环
            return true
          }
        })
      },
      // 接收 Footer 子组件传递过来的全选按钮的状态
      getFullState(val){
        this.list.forEach(item => item.goods_state = val)
      }
    },
    computed:{
      // 动态计算出全选的状态是 true 还是 false
      fullState(){
         return this.list.every(item => item.goods_state)
      },
      // 已勾选的商品总价格
      amt(){
        // 1.先filter过滤
        // 2.再reduce累加
        return this.list.filter(item=>item.goods_state).reduce((total,item)=>{
          return total+=item.goods_price * item.goods_count
        },0)
      },
      // 已勾选商品的总数量
      total(){
        return this.list.filter(item => item.goods_state).reduce((t,item)=>{
          return t+=item.goods_count
        },0)
      }
    },
    components:{
      Header,Goods,Footer
    },
    created(){
      // 调用请求数据的方法
      this.initCarList()
      bus.$on('share',val=>{
        this.list.some(item=>{
          if(item.id === val.id){
            item.goods_count = val.value
            return true
          }
        })
      })
    }
  }
</script>
<style lang="less" scoped>
  .app-container{
    padding-top: 45px;
    padding-bottom:50px
  }
</style>

这个案例对初学vue者还是有很大的借鉴意义,通过此案例了解组件之间的数据共享的各种方式,不了解的可以先看下右边这篇文章 组件的数据共享 。通过项目案例将自己所学知识融会贯通这一点非常重要,多做项目对成长的帮助非常大,希望与诸位共

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/59782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]计算机毕业设计springboot游戏商城平台论文

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

PHP 经纬度坐标相关计算方法

1. 前言 2. 计算经纬度坐标间的距离 3. 根据经纬度坐标距离排序 4. 经纬度范围查询 1. 前言 想要测试本文提供的几个功能函数&#xff0c;可以使用下面这个数据表结构及其数据 CREATE TABLE user ( id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 用户id, name v…

html静态网站基于游戏网站设计与实现共计10个页面 (仿地下城与勇士游戏网页)

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

UDS(83服务-AccessTimingParameter)

诊断协议那些事儿 诊断协议那些事儿专栏系列文章,本文介绍诊断和通讯管理功能单元下的83服务AccessTimingParameter,该服务的目的是读取/修改有效通信的计时参数。 文章目录 诊断协议那些事儿一、83服务-AccessTimingParameter二、请求格式子功能参数定义-timingParameterA…

Java并发编程—死锁

文章目录死锁什么叫做加锁&#xff1f;死锁代码理解&#xff1a;如何避免死锁&#xff1f;资源限制的挑战什么是资源限制&#xff1f;资源限制引发的问题&#xff1f;如何解决资源限制的问题&#xff1f;在资源限制情况下进行并发编程————————————————————…

物联网 (IoT) 为何如此重要?哪些技术让物联网成为了可能?

随着社会的进步和科技的发展&#xff0c;定位技术在技术手段、定位精度、可用性等方面均取得质的飞越&#xff0c;并且逐步从航海、航天、航空、测绘、军事、自然灾害预防等“高大上”的领域逐步渗透社会生活的方方面面&#xff0c;成为人们日常中不可或缺的重要应用——比如人…

[附源码]计算机毕业设计基于SpringBoot的剧本杀管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

用Python画出圣诞树,瞧瞧我这简易版的吧

前言 嗨嗨&#xff0c;大家好&#xff0c;我是小圆 今天来实现一下 用python画出圣诞树 代码 模块 源码.点击领取即可 import turtle as t from turtle import * import random as r import time圣诞树细节以及画布大小 画布大小&#xff0c;背景颜色都可以改&#xff0c;…

数据结构——链表

目录 一、链表概述 二、模拟实现链表 1、结点 2、遍历链表 3、获取链表的长度 4、添加元素 &#xff08;1&#xff09;、头插法 &#xff08;2&#xff09;、尾插法 &#xff08;3&#xff09;、在指定位置插入元素 5、删除元素 &#xff08;1&#xff09;、删…

Springboot整合mybatis多数据源

Mybatis中如何配置多数据源 一 什么情况下会用到多数据库&#xff1f; 场景1&#xff1a; 一个商城网站&#xff0c;一个游戏网站&#xff0c;商城网站已经做好&#xff0c;游戏网站正在开发&#xff0c;游戏网站上的很多道具需要用到商城网站的产品数据&#xff0c;这种情况…

[附源码]Python计算机毕业设计Django基于JEE平台springboot技术的订餐系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

wy的leetcode刷题记录_Day57

wy的leetcode刷题记录_Day57 声明 本文章的所有题目信息都来源于leetcode 如有侵权请联系我删掉! 时间&#xff1a;2022-12-1 前言 leetcode 每日一题二叉树 1779. 找到最近的有相同 X 或 Y 坐标的点 701. 二叉搜索树中的插入操作 目录wy的leetcode刷题记录_Day57声明前言1…

多目标Jaya优化算法(Matlab代码实现)

👨‍🎓个人主页:研学社的博客 💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭:行百里者,半于九十。 📋📋📋本文目录如下:🎁🎁🎁 💥1 概述 多目标 Jaya 算…

CG-FX 风向传感器 聚碳 浅谈工作原理

产品概述 本产品外型小巧轻便&#xff0c;美观坚固&#xff0c;便于携带和组装&#xff0c;风向标形状设计合理&#xff0c;对自然界大气风向具有准确的定位作用。采用聚碳材质&#xff0c;具有防雨、防腐蚀、坚固实用等优点。 功能特点 ◆体积小&#xff0c;重量轻&#xf…

[附源码]Python计算机毕业设计Django绿色生鲜

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[附源码]JAVA毕业设计酒店管理系统(系统+LW)

[附源码]JAVA毕业设计酒店管理系统&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&…

anaconda使用系列教程--3)conda命令详解

管理conda 在任何时候你可以通过在命令后边跟上-help来获得该命令的完整文档。例如&#xff0c;你可以通过如下的命令来学习conda的update命令conda update --help Conda会返回你安装Anaconda软件的版本conda --version 升级当前版本conda update conda 查看当前conda信息cond…

[附源码]计算机毕业设计打印助手平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]计算机毕业设计基于springboot的旅游景点管理系统的设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

JSP+MySQL基于ssm的主题酒店管理系统

以往的主题酒店管理事务处理主要使用的是传统的人工管理方式,这种管理方式存在着管理效率低、操作流程繁琐、保密性差等缺点,长期的人工管理模式会产生大量的文本餐饮预订与文本数据,这对事务的查询、更新以及维护带来不少困难。随着互联网时代的到来,现如今网络的覆盖率已近非…