vue3仿美团项目(4)-店铺开发

一、文件结构目录

二、效果

一开始显示红色的圈圈,点击之后显示步进器(stepper);

点击加入购物车,可以购物车对应的图标上会有显示;

点击购物车和立即购买,都会跳转到首页下购物车的页面。

三、各个文件代码

1.MyStore.vue

<template>
  <div class="storeDetails">
    <Header title="店铺" />
    <div class="content">
      <div class="img"></div>
      <div class="foodClassify">
        <div class="name">
          {{ title }}
          <img :src="img" class="store_img" />
        </div>
        <div class="classify">
          <van-tabs color="#ffc400">
            <van-tab
              v-for="(i, index) in storeData"
              :key="index"
              :title="i.name"
            >
              <Food-list :index="index" :foodData="i.data" />
            </van-tab>
          </van-tabs>
        </div>
      </div>
    </div>
    <!-- 尾部 -->
    <van-action-bar>
      <van-action-bar-icon icon="chat-o" text="客服" @click="service" />
      <van-action-bar-icon
        icon="cart-o"
        text="购物车"
        :badge="store.state.cartList.length"
        @click="goCart"
      />
      <van-action-bar-button
        type="warning"
        text="加入购物车"
        @click="handleAddCart"
      />
      <van-action-bar-button type="danger" text="立即购买" @click="clickBuy" />
    </van-action-bar>
  </div>
</template>
<script>
import { defineComponent, reactive, toRefs } from "vue";
import Header from "../../components/Header.vue";
import FoodList from "./components/foodList.vue";
import { Toast } from "vant";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
// import { showToast } from 'vant';
export default defineComponent({
  name: "App",
  components: { Header, FoodList },
  setup() {
    const store = useStore();
    const router = useRouter();
    let data = reactive({
      title: "鱼拿酸菜鱼",
      img: "https://img1.baidu.com/it/u=1599947592,1695977044&fm=253&fmt=auto&app=138&f=JPEG?w=640&h=440",
      storeData: [
        {
          name: "点菜",
          data: {
            content: "点菜",
            items: [
              {
                text: "热销套餐",
                children: [
                  {
                    pic: "https://img1.baidu.com/it/u=1599947592,1695977044&fm=253&fmt=auto&app=138&f=JPEG?w=640&h=440",
                    title: "招牌酸菜鱼",
                    num: 0,
                    price: 25.0,
                    id: 0,
                    add: true,
                  },
                  {
                    pic: "https://img1.baidu.com/it/u=1599947592,1695977044&fm=253&fmt=auto&app=138&f=JPEG?w=640&h=440",
                    title: "藤椒酸菜鱼",
                    num: 0,
                    price: 25.0,
                    id: 1,
                    add: true,
                  },
                ],
              },
              {
                text: "澳洲肥牛",
                children: [
                  {
                    pic: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbkimg.cdn.bcebos.com%2Fpic%2F8694a4c27d1ed21b0ef4f3137f24cac451da80cb91b8&refer=http%3A%2F%2Fbkimg.cdn.bcebos.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1645407747&t=ea2c9f772ba0df3a2d1b00b962875460",
                    title: "酸汤肥牛",
                    num: 0,
                    price: 25.0,
                    id: 3,
                    add: true,
                  },
                  {
                    pic: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fbkimg.cdn.bcebos.com%2Fpic%2F8694a4c27d1ed21b0ef4f3137f24cac451da80cb91b8&refer=http%3A%2F%2Fbkimg.cdn.bcebos.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1645407747&t=ea2c9f772ba0df3a2d1b00b962875460",
                    title: "香辣肥牛",
                    num: 0,
                    price: 25.0,
                    id: 4,
                    add: true,
                  },
                ],
              },
              {
                text: "超级折扣",
                children: [
                  {
                    pic: "https://img1.baidu.com/it/u=1599947592,1695977044&fm=253&fmt=auto&app=138&f=JPEG?w=640&h=440",
                    title: "无骨酸菜鱼+肥牛双拼",
                    num: 0,
                    price: 25.0,
                    id: 5,
                    add: true,
                  },
                  {
                    pic: "https://img1.baidu.com/it/u=1599947592,1695977044&fm=253&fmt=auto&app=138&f=JPEG?w=640&h=440",
                    title: "香辣水煮鱼+肥牛双拼",
                    num: 0,
                    price: 25.0,
                    id: 6,
                    add: true,
                  },
                ],
              },
            ],
          },
        },
        { name: "评价", data: { content: "评价" } },
        { name: "商家", data: { content: "商家" } },
      ],
    });
    // 客服
    const service = () => {
      // showToast('提示内容');
      Toast.fail("敬请期待...");
      // Toast("敬请期待...")
    };
    // 点击购物车按钮
    const goCart = () => {
      router.push("/cart");
    };
    //  添加到购物车
    const handleAddCart = (type) => {
      let newList = [];
      data.storeData.forEach((item) => {
        item.data.items?.forEach((items) => {
          items.children.forEach((itemss) => {
            if (itemss.num > 0) {
              newList.push(itemss);
            }
          });
        });
      });
      if (newList.length == 0) {
        Toast.fail("请选择商品");
        return;
      }
      store.commit("ADDCART", newList);
      type == "buy" ? goCart() : "";
    };

    //立即购买
    const clickBuy = () => {
      handleAddCart(buy);
    };
    return {
      ...toRefs(data),
      service,
      handleAddCart,
      clickBuy,
      goCart,
      store
    };
  },
});
</script>
<style lang="less" scoped>
.storeDetails {
  height: 100%;
  display: flex;
  flex-flow: column;
  .content {
    flex: 1;
    overflow-y: auto;
    .img {
      width: 100%;
      height: 150px;
      background: url("../../assets/yuna.jpg") no-repeat center/cover;
    }
    .foodClassify {
      height: 500px;
      background-color: #fff;
      border-radius: 20px 20px 0 0;
      margin-top: -30px;
      .name {
        display: flex;
        padding: 20px;
        justify-content: space-between;
        font-size: 39px;
        .store_img {
          width: 80px;
          height: 80px;
          border-radius: 10px;
          margin-top: -30px;
        }
      }
    }
  }
}
</style>

 2.foodList.vue

<template>
  <div class="food_list" v-if="index == 0">
    <van-tree-select
      height="88vw"
      :items="items"
      :main-active-index.sync="active"
      @click-nav="navClick"
    >
      <template #content>
        <div v-for="(i, index) in subItem" :key="index" class="item_bg">
          <FoodAdd
            :item="i"
            :showAdd="true"
            :addClick="addClick"
            :onChange="onChange"
            showAdd="true"
          />
        </div>
      </template>
    </van-tree-select>
  </div>
</template>
<script>
import { defineComponent, reactive, toRefs } from "vue";
import FoodAdd from "../../../components/FoodAdd.vue";
export default defineComponent({
  name: "App",
  props: ["index", "foodData"],
  components: { FoodAdd },
  setup(props) {
    let data = reactive({
      items: [],
      active: 0,
      subItem: [],
    });
    // console.log("foodData", props.foodData);
    // 初始化数据
    const init = () => {
      const newList = [];
      props.foodData?.items?.map((item, index) => {
        newList.push({ text: item.text });
        if (data.active == index) {
          data.subItem = item.children;
        }
      });
      // console.log("1.subItem", subItem);
      data.items = newList;
      // console.log("newlist",newList);
    };
    init();
    // console.log("2.subItem", data.subItem);

    const navClick = (i) => {
      data.active = i;
      init();
    };
    // 切换步进器
    const addClick = (i) => {
      data.subItem.forEach((item) => {
        if (item.id == i) {
          item.add = false;
          item.num = 1;
        }
      });
    };
    // 步进器数量发生变化
    const onChange = (value, datail) => {
      data.subItem.forEach((item) => {
        if (item.id == datail.name) {
          item.num = value;
        }
      });
      console.log("data.subItem", data.subItem);
    };

    return {
      ...toRefs(data),
      navClick,
      addClick,
      onChange,
    };
  },
});
</script>
<style lang="less" scoped>
.food_list {
  margin-top: 20px;
  .item_bg {
    padding: 10px;
  }
}
/deep/ .van-sidebar-item--select::before {
  background-color: #ffc400;
}
</style>

3.FoodAdd.vue

<template>
  <div class="content_item">
    <div class="left">
      <img :src="item.pic" />
      <div class="text">
        <div class="title">{{ item.title }}</div>

        <van-icon
          name="add-o"
          v-if="item.add && showAdd"
          @click="addClick(item.id)"
        />
        <van-stepper
          v-model="item.num"
          min="1"
          v-else
          :name="item.id"
          @change="onChange"
        />
      </div>
    </div>
    <div class="right">¥{{ item.price }}</div>
  </div>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
  name: "App",
  props: ["item", "onChange", "addClick", "showAdd"],
  setup() {
    // console.log("2.item", props.item);
  },
});
</script>
<style lang="less" scoped>
.content_item {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
}
.right {
  font-size: 16px;

  font-weight: 600;
}
.left {
  display: flex;
  align-items: center;
  flex: 1;
  img {
    margin-left: 10px;
    width: 60px;
    height: 60px;
    margin-right: 10px;
    border-radius: 10px;
  }
  .text {
    display: flex;
    flex-flow: column;
    justify-content: space-between;
    height: 100%;
    position: relative;
    flex: 1;
    .title {
      font-size: 16px;
    }
    .van-icon {
      color: red;
      font-size: 20px;
      position: absolute;
      right: 4px;
      bottom: 4px;
    }
  }
}
</style>

4.main.js

import { createApp } from 'vue'
import App from './App.vue'
import 'amfe-flexible'
import { Button, Icon, Tab, Tabs, TreeSelect, Stepper, ActionBar, ActionBarIcon, ActionBarButton, Toast } from 'vant'
import router from './router'
import "./common/css/base.less"
import store from './store'
const app = createApp(App)
app.use(router)
app.use(Button).use(Icon).use(Tab).use(Tabs).use(TreeSelect).use(Stepper).use(ActionBar).use(ActionBarIcon).use(ActionBarButton).use(Toast)
app.use(store)
app.mount('#app')

5.store(vuex)-->index.js

安装vuex,    npm i vuex@next -S

import { createStore } from "vuex";
export default createStore({
    state: {
        cartList: []
    },
    mutations: {
        ADDCART(state, value) {
            state.cartList = value
        }
    },
    actions: {

    }
})

四、上传git

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值