Vue+springboot简单实现点餐系统开发

项目进行前后端分离
后端采用springboot+mybatis+mysql数据库提供数据接口
前端采用Vue框架获取数据实现页面数据渲染、页面路由
借助springboot实现数据接口,主要内容是Vue实现前端页面功能的流程步骤

文章目录

        • 一、准备环境
          • 1、后台数据接口
          • 2、vue项目环境
        • 二、底部导航
          • 1、图标准备
          • 2、初始页面组件
          • 3、路由配置
          • 4、导航组件
          • 5、全局app
        • 三、首页轮播
          • 1、数据格式
          • 2、轮播插件
          • 3、首页
        • 四、商品分类
          • 1、分类标签
          • 2、分类样式
          • 3、axios获取数据
        • 五、商品列表
          • 1、列表页面
          • 2、动态路由
        • 六、购物车
          • 1、页面布局
          • 2、样式
          • 3、方法

一、准备环境

1、后台数据接口

轮播图片:http://localhost:8080/data/images

["http://localhost:8080/data/static/fl_03.jpg",
"http://localhost:8080/data/static/fl_06.jpg",
"http://localhost:8080/data/static/fl_11.jpg",
"http://localhost:8080/data/static/fl_14.jpg"]

商品分类:http://localhost:8080/data/types

[{
     "id":1,"name":"甜品","img":"http://localhost:8080/data/static/fl_03.jpg"},
{
     "id":2,"name":"蛋糕","img":"http://localhost:8080/data/static/fl_06.jpg"},
{
     "id":3,"name":"饼干","img":"http://localhost:8080/data/static/fl_11.jpg"},
{
     "id":4,"name":"面包","img":"http://localhost:8080/data/static/fl_14.jpg"}]

商品列表:http://localhost:8080/data/foods

[{
     "id":1,"name":"芒果慕斯","img":"http://localhost:8080/data/static/good.jpg","price":16,"star":5,"typeId":1},
{
     "id":2,"name":"蓝莓蛋挞","img":"http://localhost:8080/data/static/gooddetail.jpg","price":20,"star":4,"typeId":1},
{
     "id":3,"name":"草莓蛋糕","img":"http://localhost:8080/data/static/good.jpg","price":12,"star":5,"typeId":1},
{
     "id":4,"name":"黑森林","img":"http://localhost:8080/data/static/gooddetail.jpg","price":18,"star":5,"typeId":1},
{
     "id":5,"name":"风味曲奇","img":"http://localhost:8080/data/static/gooddetail.jpg","price":20,"star":5,"typeId":2}]

后端springboot项目结构为:
Vue+springboot简单实现点餐系统开发_第1张图片

2、vue项目环境

1)、创建vue项目

创建教程:https://blog.csdn.net/booy123/article/details/107127049#2_862

2)、vue项目清理

删除文件:views目录下的文件,components目录下的文件

清理文件内容:

app.vue

<template>
  <div id="app">
  div>
template>

<style lang="scss">

style>

路由js文件

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [

]

const router = new VueRouter({
     
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

清理后的项目结构图
Vue+springboot简单实现点餐系统开发_第2张图片

二、底部导航

1、图标准备

地址:https://www.iconfont.cn/

选择需要的图标加入购物车>添加至项目,在个人中心项目中进行下载到本地,把下载的图标文件夹放在public下

2、初始页面组件

views目录下创建四个初始页面(Cart.vue、Index.vue、Order.vue、User.vue),空页面即可

模板代码:

<template>
    <div>个人中心div>
template>
<script>
export default {
      }
script>
<style scoped>
style>
3、路由配置

router/index.js进行路由配置

import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from '../views/Index'
import User from '../views/User'
import Cart from '../views/Cart'
import Order from '../views/Order'

Vue.use(VueRouter)

const routes = [
  {
     
    path: '/index',
    component: Index
  },
  {
     
    path: '/user',
    component: User
  },
  {
     
    path: '/cart',
    component: Cart
  },
  {
     
    path: '/order',
    component: Order
  },
  {
     
    path: '*',
    component: Index
  }
]

const router = new VueRouter({
     
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
export default router
4、导航组件
<template>
  <nav>
    <ul>
      <router-link to="/index" tag="li" activeClass="active">
        <i class="iconfont">i>
        首页
      router-link>
      <router-link to="/cart" tag="li" activeClass="active">
        <i class="iconfont">i>
        购物车
      router-link>
      <router-link to="/order" tag="li" activeClass="active">
        <i class="iconfont">i>
        订单
      router-link>
      <router-link to="/user" tag="li" activeClass="active">
        <i class="iconfont">i>
        我的
      router-link>
    ul>
  nav>
template>
<script>
export default {
      }
script>
<style lang="scss" scoped>
  .active{
      color: red}
  nav{
      
    position: fixed;
    bottom: 0px;
    left: 0;
    width: 100%;
    height: 50px;
    background-color: white;
    ul{
      
      display: flex;
      li{
      
        flex: 1;
        line-height: 50px;
        text-align: center;
      }
    }
  }
style>

图标生效,在index.html中引入图标样式

<link rel="stylesheet" href="<%= BASE_URL %>iconfont/iconfont.css">
5、全局app

app.vue中注册导航组件

<template>
  <div id="app">
    <router-view>router-view>
    <tabbar>tabbar>
  div>
template>
<script>
import tabbar from './components/Tabbar.vue'
export default {
      
  components: {
      
    tabbar: tabbar
  }
}
script>

<style lang="scss">
*{
      
  margin: 0;
  padding: 0;
}
  html{
      
    height: 100%;
  }
  li{
      
    list-style: none;
  }
style>

浏览器效果:
Vue+springboot简单实现点餐系统开发_第3张图片

三、首页轮播

1、数据格式
[
  "http://localhost:8080/data/static/f1_03.jpg",
  "http://localhost:8080/data/static/f1_06.jpg",
  "http://localhost:8080/data/static/f1_11.jpg",
  "http://localhost:8080/data/static/f1_14.jpg"
]
2、轮播插件

封装Swiper.vue,此处引入一个导航插件

cnpm install --save swiper

注意下载的swiper文件路径,不同版本文件位置和名称可能会略微变化

<template>
  <div class="swiper-container foodswiper">
    
    <div class="swiper-wrapper">
      <slot>
      slot>
    div>
    
    <div class="swiper-pagination">div>
  div>
template>
<script>
import Swiper from 'swiper'
import 'swiper/css/swiper.css'
export default {
      
  mounted () {
      
    // 页面加载完后进行初始化轮播组件
    /* eslint-disable no-new */
    new Swiper('.foodswiper', {
      
      loop: true, // 是否循环轮播
      autoplay: {
      
        delay: 2000 // 延迟2s轮播
      },
      pagination: {
       // 分页放的位置
        el: '.swiper-pagination'
      }
    })
  }
}
script>
<style lang="scss" scoped>
  .swiper-wrapper {
      
    img {
      
      width: 100%;
    }
  }
style>
3、首页

Index.vue

<template>
    <div>
      
      <swiper :key="loopList.length">
        <div class="swiper-slide" v-for="n in loopList" :key="n">
          <img :src="n">
        div>
      swiper>
    div>
template>
<script>
import swiper from '@/components/Swiper'
import axios from 'axios'
export default {
      
  components: {
      
    swiper
  },
  data () {
      
    return {
      
      loopList: []
    }
  },
  mounted () {
       // 页面加载完后获取后端数据
    axios({
      
      url: '/data/images'
    }).then(res => {
      
      console.log(res.data)
      this.loopList = res.data
    })
  }
}
script>

浏览器轮播效果:
Vue+springboot简单实现点餐系统开发_第4张图片

四、商品分类

修改当前页Index.vue

1、分类标签

商品分类标签

<div id="head-bar">
  商品分类
div>
<div class="cat-list">
  <div v-for="c in categories" :key="c.id">
    <img :src="c.img" />
  div>
div>
2、分类样式

3、axios获取数据

安装axios插件npm install axios
根目录src下创建vue.config.js文件:

module.exports = {
     
  devServer: {
     
    proxy: {
     
      '/types': {
     
        target: 'http://localhost:8080',
        changeOrigin: true
      }
    }
  }
}

当前页js进行数据请求

axios({
     
  url: '/data/types'
}).then(res => {
     
  console.log(res.data)
  this.categories = res.data
})

浏览器效果:
Vue+springboot简单实现点餐系统开发_第5张图片

五、商品列表

1、列表页面

创建Food.vue组件

<template>
    <div>
      <div class="shop">
        <div class="goods" v-for="i in foodList" :key="i.id">
          <div class="goodsbox">
            <img :src="i.img">
            <div class="title1">¥{
    {i.price}}div>
            <div class="title2">{
    {i.name}}div>
            
div> div> div> div> div> template> <script> import axios from 'axios' export default { data () { return { foodList: [] } }, mounted () { console.log(this.$route.params.id) // 输出动态id axios({ url: '/data/foods?typeId=' + this.$route.params.id }).then(res => { this.foodList = res.data }) } } script> <style lang="scss" scoped> .shop { position: relative; top: 20px; padding: 1%; .goods { width: 50%; float: left; text-align: center; .goodsbox { background: #fff; width: 90%; margin: 10px; height: 160px; position: relative; box-shadow: 0 0 2px #d8d8d8; } img { width: 100%; height: 100px; } .title1 { width: 50px; height: 50px; border-radius: 50%; position: absolute; top: 75px; background-color: #fff; margin-left: 55px; text-align: center; line-height: 35px; } .title2 { position: absolute; width: 100%; text-align: center; } .title3 { position: absolute; top: 130px; text-align: center; width: 60px; height: 20px; background-color: #393939; color: #fff; border-radius: 5px; left: 30%; } } } style>
2、动态路由

router/index.js下配置

{
     
  path: '/food/:id',
  component: Food
}

Index.vue下配置

动态列表点击事件

<img :src="c.img" @click="changePage(c.id)"/>
methods: {
     
  changePage: function (id) {
     
    console.log(id)
    this.$router.push(`/food/${
       id}`) // 传url动态参数,这里不是单引号,ES6的模板
  }
}

点击分类图进入,浏览器显示:
Vue+springboot简单实现点餐系统开发_第6张图片

六、购物车

1、页面布局

<div class="cart-detail" v-show="showCartDetail">
  <div class="mask" @click="hideCart">div>
  <div class="list">
    <div class="carttit">
      <div class="carttit0">购物车div>
      <div class="cartempty" @click="clearCart"><img src="../assets/del.jpg" class="cartimg"/>清空div>
    div>
    <div class="carttxt">
      <div class="carttxt0">满减div>
      <div class="carttxt1">订单满100m免运费\配送费div>
    div>
    <div class="item-list">
      <div class="item" v-for="i in cart.list" :key="i.food.id">
        <div class="name ellipsis">{
    {i.food.name}}div>
        <div class="total">¥{
    {i.food.price}}div>
        <div class="reduce" @click="reduceCart(i.food)">-div>
        <div class="num">{
    {i.num}}div>
        <div class="add" @click="addToCart(i.food)">+div>
      div>
    div>
  div>
div>
<div class="cart">
  <div class="data">
    <div class="icon" @click="showCart">
      <img src="../assets/cart.png"/>
      <div class="count">{
    {cart.count}}div>
    div>
    <div class="total">¥{
    {cart.total}}div>
  div>
  <div class="button" :class="{disable:isDisable}">
    结算
  div>
div>
2、样式
/*下方购物车*/
.cart-detail {
     
  .mask {
     
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 999999;
    background: rgba(0, 0, 0, 0.7);
  }
  .list {
     
    position: absolute;
    left: 0;
    bottom: 0px;
    width: 100%;
    background: #f7f7f7;
    padding: 0 0 70px;
    z-index: 999999;
    .item-list {
     
      height: 130px;
      overflow: scroll;
    }
  }
  .item {
     
    display: -webkit-flex;
    color: #333;
    font-size: 12px;
    line-height: 20px;
    padding: 5px 15px;
    border-bottom: 1px solid #d5d5d5;
    .name {
     
      -webkit-flex: 1;
      font-size: 12px;
      color: #606060;
    }
    .reduce, .add {
     
      font-size: 14px;
      background: #4a4a4a;
      width: 20px;
      height: 20px;
      text-align: center;
      border-radius: 50%;
      color: #fff;
      line-height: 20px;
      border: 1px solid #4a4a4a
    }
    .reduce {
     
      background: #ffffff;
      color: #4a4a4a;
    }
    .total {
     
      width: 120px;
      font-size: 13px;
      color: #373737;
      font-weight: bold
    }
    .num {
     
      width: 30px;
      text-align: center;
      margin: 0 5px;
      color: #4a4a4a
    }
  }
}

.cart {
     
  display: -webkit-flex;
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 50px;
  background: #3c3d41;
  z-index: 999999;
  .data {
     
    -webkit-flex: 1;
    .icon {
     
      position: absolute;
      left: 20px;
      top: -25px;
      width: 50px;
      height: 50px;
      background: #393939;
      border-radius: 50%;
      border: 5px solid #3c3d41;
      box-shadow: 0 0 5px #000;
      img {
     
        position: absolute;
        width: 40px;
        height: 40px;
        top: 5px;
        left: 5px;
      }
      .count {
     
        position: absolute;
        left: 35px;
        top: -10px;
        font-size: 12px;
        width: 25px;
        height: 25px;
        line-height: 25px;
        color: #fff;
        background: #f45044;
        border-radius: 50%;
        text-align: center;
      }
    }
    .total {
     
      color: #f45044;
      font-size: 16px;
      line-height: 40px;
      padding-left: 90px;
      font-weight: bolder;
    }
  }
  .button {
     
    width: 100px;
    height: 100%;
    font-size: 14px;
    background: #f38815;
    color: #fff;
    line-height: 50px;
    text-align: center;
  }
  .disable {
     
    color: #fff;
    background-color: #333333;
  }
}

.carttit {
     
  background: #e5e5e5;
  padding: 0 10px;
  height: 50px;
  line-height: 50px;
}

.carttit0 {
     
  width: 200px;
  margin-top: 10px;
  height: 30px;
  font-size: 16px;
  float: left;
  color: #4a4a4a;
  line-height: 30px;
  border-left: 4px solid #ffa404;
  text-indent: 15px;
}

.cartempty {
     
  font-size: 12px;
  float: right;
  color: #4a4a4a;
  text-align: right;
}

.carttxt {
     
  padding: 0 15px;
  height: 40px;
  line-height: 40px;
  border-bottom: 1px solid #d5d5d5
}

.carttxt0 {
     
  width: 50px;
  height: 25px;
  font-size: 12px;
  float: left;
  color: #f38d1e;
  margin-top: 6px;
  line-height: 25px;
  border: 1px solid #f38d1e;
  text-align: center;
  border-radius: 3px;
  margin-right: 5px;
}

.carttxt1 {
     
  float: left;
  font-size: 12px;
  color: #4a4a4a;
  text-align: right
}

.cartimg {
     
  width: 15px;
  height: 20px;
  position: relative;
  top: 5px;
  margin-right: 3px;
}
3、方法
<script>
import axios from 'axios'
export default {
     
  data () {
     
    return {
     
      foodList: [],
      cart: {
     
        count: 0, // 商品数量
        total: 0, // 商品总价
        list: {
     } // 键值对对象,以商品id为key,商品和商品数量为value
      },
      showCartDetail: false, // 默认不展示,点击购物车图标是为true
      isDisable: true // 默认样式不可点击
    }
  },
  mounted () {
     
    console.log(this.$route.params.id) // 输出动态id
    axios({
     
      url: '/data/foods?typeId=' + this.$route.params.id
    }).then(res => {
     
      this.foodList = res.data
    })
  },
  methods: {
     
    // 添加商品
    addToCart: function (food) {
     
      this.cart.count++
      this.cart.total += food.price
      if (this.cart.list[food.id]) {
      // 表示list里存在当前添加商品
        this.cart.list[food.id].num++
      } else {
     
        var temp = {
      food: food, num: 1 } // 新加入的商品赋值数量为1
        this.cart.list[food.id] = temp // key(food.id)和value(temp)进行存储
      }
      this.isDisable = false
      console.log(this.cart.list)
    },
    // 减去商品
    reduceCart: function (food) {
     
      this.cart.count--
      this.cart.total -= food.price
      this.cart.list[food.id].num--
      if (this.cart.list[food.id].num === 0) {
      // 为0时删除商品
        delete this.cart.list[food.id]
      }
      if (this.cart.count === 0) {
     
        this.isDisable = true
      }
    },
    // 清空购物车
    clearCart: function () {
     
      this.cart.count = 0
      this.cart.total = 0
      this.cart.list = {
     }
      this.isDisable = true
    },
    hideCart: function () {
     
      this.showCartDetail = false
    },
    // 显示购物车
    showCart: function () {
     
      this.showCartDetail = true
    }
  }
}
</script>

浏览器显示效果:
Vue+springboot简单实现点餐系统开发_第7张图片
Vue+springboot简单实现点餐系统开发_第8张图片
源码地址:https://download.csdn.net/download/booy123/12589350

你可能感兴趣的:(WEB前端,vue,html,js,css,java)