简单实现外卖demo

在这里插入图片描述

  1. 关于加减菜单思路是:单独写一个组件,然后父向子组件传参,把这一项的数据都传过去;数据后端返回的肯定是个对象类型,在点击加减号时,触发vuex方法,动态给这个对象增减属性count
  2. 其他的其实也没啥难的,主要是会vuex的用法

main.js代码

import Vue from 'vue'
import App from './App.vue'
import store from './store/index'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

Vue.config.productionTip = false

new Vue({
  store,
  render: h => h(App),
}).$mount('#app')

vuex代码

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const state = {
    totalCount: '', //菜单总数量
    totalPrice: '', //菜单总价格
    cartFoods: [],
    list: [
        {
            name: "麻婆豆腐",
            price: 6
        },
        {
            name: "回锅肉",
            price: 8
        },
        {
            name: "红烧肉",
            price: 4
        },
        {
            name: "宫保鸡丁",
            price: 7
        },
        {
            name: "酸菜鱼",
            price: 15
        },
        {
            name: "鱼香肉丝",
            price: 25
        },
        {
            name: "糖酥排骨",
            price: 21
        },
        {
            name: "小葱拌豆腐",
            price: 3
        },
        {
            name: "拍黄瓜",
            price: 5
        },
        {
            name: "宫保鸡丁",
            price: 5
        },
        {
            name: "酸菜鱼",
            price: 5
        },
        {
            name: "鱼香肉丝",
            price: 5
        },
        {
            name: "糖酥排骨",
            price: 5
        },
        {
            name: "小葱拌豆腐",
            price: 5
        },
        {
            name: "拍黄瓜",
            price: 5
        },

    ],
}

const getters = {
    // 菜单总数量
    totalCount(state) {
        return state.cartFoods.reduce((preTotal, food) => preTotal + food.count, 0)
    },
    // 菜单总价格
    totalPrice(state) {
        return state.cartFoods.reduce((preTotal, food) => preTotal + food.count * food.price, 0)
    }
}

const mutations = {
    // 加菜单
    add(state, { food }) {
        if (!food.count) {
            Vue.set(food, 'count', 1)
            state.cartFoods.push(food)
        } else {
            food.count++
        }
    },
    // 加菜单
    dec(state, { food }) {
        if (food.count) {
            food.count--
            if(food.count === 0) {
                state.cartFoods.splice(state.cartFoods.indexOf(food), 1)
            }
        }
    },
    // 清空菜单
    clears(state) {
        state.cartFoods.forEach(food => food.count = 0);
        state.cartFoods = [];
    }
}

const actions = {
    // 加减菜单
    update(context, { isAdd, food }) {
        if (isAdd) {
            context.commit('add', { food })
        } else {
            context.commit('dec', { food })
        }
    },
    // 清空菜单
    clear(context) {
        context.commit('clears')
    }
}

const store = new Vuex.Store({
    state,
    getters,
    mutations,
    actions
})

//暴露store
export default store

index.vue代码

<template>
  <div class="bigBox">
    <div class="header">来份外卖</div>
    <div class="container">

      <div class="left">
        <div class="lheight">招牌</div>
        <div class="lheight">热销</div>
        <div class="lheight">青菜</div>
        <div class="lheight" style="background: #fff">荤菜</div>
        <div class="lheight">饮料</div>
        <div class="lheight">小吃</div>
        <div class="lheight">烧烤</div>
      </div>

      <div class="right">
        <div class="border" v-for="(food,index) in list" :key="index">
          <div class="name">
            {{ food.name }}
            <span style="color: red">{{ food.price }}</span>
          </div>
          <div class="ctr">
            <cartCtr :food="food"></cartCtr>
          </div>
        </div>
      </div>
    </div>
    <div class="footer">
      <cartBus></cartBus>
    </div>
  </div>
</template>

<script>
import { mapState } from "vuex";
import cartCtr from "./views/cartCtr";  //控件
import cartBus from "./views/cartBus";  //购物车
export default {
  name: "index",
  components: {
    cartCtr,
    cartBus,
  },
  data() {
    return {};
  },
  computed: {
    ...mapState(["list"]),
  },
  created() {},
  mounted() {},
};
</script>

cartBus.vue代码

<template>
  <div class="cartBus">
    <div class="show" v-if="listShow">
      <div class="title">
        <div class="bus">购物车</div>
        <button class="clear" @click="clear">清空</button>
      </div>
      <div class="foodList">
        <div class="rightCtr" v-for="(item,index) in cartFoods" :key="index">
          <div class="yu">{{ item.name }}</div>
          <div>
              <cartCtr :food="item"></cartCtr>
          </div>
        </div>
      </div>
    </div>
    <div class="bottom">
      <div @click="clickFalg">
        <span>bus</span>
        <span class="one" v-if="totalCount">{{ totalCount }}</span>
      </div>
      <div v-if="totalPrice">{{ totalPrice }}</div>
      <button>去结算</button>
    </div>
  </div>
</template>

<script>
import cartCtr from "./cartCtr";
import { mapState, mapGetters } from "vuex";
export default {
  name: "carBus",
  components: {
      cartCtr
  },
  data() {
    return {
      flag: false,
    };
  },
  created() {},
  mounted() {},
  methods: {
    clickFalg() {
      this.flag = !this.flag;
    },
    clear() {
        this.flag = false;
        this.$store.dispatch('clear')
    }
  },
  computed: {
    ...mapState(["cartFoods"]),
    ...mapGetters(["totalCount", "totalPrice"]),
    // 当count为0时,购物车隐藏
    listShow() {
        if(this.totalCount === 0) {
            return false
        }
        return this.flag;
    }
  },
};
</script>

cartCtr.vue代码

<template>
  <div>
    <span class="border" v-if="food.count" @click="update(false)">-</span>
    <span class="num" v-if="food.count">{{ food.count }}</span>
    <span class="border" @click="update(true)">+</span>
  </div>
</template>

<script>
export default {
  name: "cartCrt",
  props: {
    food: Object,
  },
  data() {
    return {};
  },
  created() {},
  mounted() {},
  methods: {
      update(isAdd) {
          this.$store.dispatch('update', {isAdd, food: this.food})
      }
  }
};
</script>

项目结构

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值