Day46:项目-购物车案例

购物车案例

  1. 准备工作
    1. 首页默认加载,其余页面懒加载

    2. 调用defineStore方法构建store

    3. 入口main做对应配置,找指南,快速开始,把elementplus引入进来
import { createApp } from "vue";
import { createPinia } from "pinia";
import "./style.css";
import App from "./App.vue";
import router from "./router";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
const app = createApp(App);
const pinia = createPinia();
app.use(router);
app.use(pinia);
app.use(ElementPlus);
app.mount("#app");
    1. api就是用来模拟后台接口的

  1. 在app.vue中做购物车首页,头部不进入路由,在头部的底部放RouterView
  2. 给app 的header添加插槽#header,写类名添加样式,头部插槽内的内容不会发生变化
<template>
  <div>
    <el-card class="box-card">
      <template #header>
        <div class="card-header">
          <h1>购物车首页</h1>
          <div class="btn">
            <RouterLink to="/productlist">
              <el-button type="primary">商品列表</el-button></RouterLink
            >
            <RouterLink to="/shoppingcar"
              ><el-button type="primary">购物车</el-button></RouterLink
            >
          </div>
        </div>
      </template>
      <RouterView />
    </el-card>
  </div>
</template>
    1. 写购物车首页的标题
    2. 写el-button:商品列表,购物车。并用routerLink包裹,做一个导航,并为RouterLink添加to页面
  1. 在商品列表页面,写一个el-table,
<template>
    <div class="product-list">
      <el-table :data="shoppingCarStore.productList" stripe style="width: 100%">
        <el-table-column prop="id" label="序号" align="center" />
        <el-table-column prop="title" label="商品名称" align="center" />
        <el-table-column prop="price" label="商品价格" align="center" />
        <el-table-column prop="number" label="库存" align="center" />
        <el-table-column prop="address" label="操作" align="center">
          <template #default="scope">
            <el-button type="success" @click="add(scope.row)">
              添加到购物车
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </template>
  1. 在store中写方法,初始化商品列表和初始化商品数据的方法
import { defineStore } from "pinia";
import { computed, ref } from "vue";
import { getProducts } from "../api/product";
import { ElMessage } from "element-plus";
import { buyProducts } from "../api/product.js";
const useShoppingCarStore = defineStore("shopping-car", () => {
  //初始化商品列表数据
  const productList = ref([]);
  //初始化购物车列表数据
  const shopCarList = ref([]);
    1. 一秒钟之后获取到数据(模拟从接口获取数据),
//1s中之后返回数组数据
export const getProducts = async ()=>{
    //为了模拟真实的接口请求
    await wait(1000)
    return products
}
    1. 方法在数据获取的部分有定义。
    2. 把两个需要给视图使用的方法从store中导出,并在商品列表中导入方法
    3. 绑定在table中,
  1. 给table添加按钮
    1. 改变button样式
    2. 绑定add方法,在页面中传参scope.row,代表点选的那一行。(scope代表插槽的作用域)在方法中传参row
<script setup>
import { useShoppingCarStore } from "../store";
const shoppingCarStore = useShoppingCarStore();
shoppingCarStore.getProductList();
function add(row) {
  //调用 将数据添加到购物车的方法
  shoppingCarStore.addShopCarList(row);
}
</script>
  1. 在store中写给购物车添加数据的方法
    1. 减去商品列表页面的库存:res的item id === row id时,下转判断,判断完自减--
    2. 添加购物车列表页面的商品数量,_res的item id === row id时,下转判断
      1. 在store中定义初始化购物车列表
      2. 判断购物车中是否已经存在这个商品
      3. 如果存在,将商品数量+1(_res.number++
      4. 如果没有,添加一个新商品(起始数量一定是1
    1. 判断当库存<1,写一个提示,商品已经妹有了,存在一秒。
    2. 导出方法并在列表页调用,放在add方法中,add传入的参数为row,指在点选的那一行。
const useShoppingCarStore = defineStore("shopping-car", () => {
  //初始化两行
......
  //初始化商品列表数据的方法(使用async方法,没有一大堆回调函数
  const getProductList = async () => {
    const res = await getProducts();
    productList.value = res;
  };
  // const getProductList = () => {
  //   getProducts().then((res) => {
  //     productList.value = res;
  //   });
  // };
  //给购物车添加数据的方法
  const addShopCarList = (row) => {
    //1. 减去商品列表页面的商品库存
    const res = productList.value.find((item) => item.id === row.id);
    if (res.number < 1) {
      ElMessage.error({
        message: "没有库存辣!",
        duration: 1000,
      });
      return;
    }
    res.number--;
    //2. 添加购物车列表页面的商品数量
    const _res = shopCarList.value.find((item) => item.id === row.id);
    //2.1 判断购物车列表数据中是否包含当前的商品 如果包含 让数量自增
    //2.2 如果不包含 将这个商品添加到购物车列表
    if (!_res) {
      shopCarList.value.push({
        id: row.id,
        title: row.title,
        price: row.price,
        number: 1,
      });
    } else {
      _res.number++;
    }
    //给购物车列表中的商品按照id的升序做一个排序
    shopCarList.value.sort((a, b) => {
      return a.id - b.id;
    });
  };
...
  return{...addShopCarList,...};
  1. 在购物车列表中写el-table
    1. 引入useshoppingcarstore,并绑定数据.shopCarList
    2. 绑定prop属性,表示绑定了哪个属性
  1. 在store中添加排序功能,商品加入购物车后按照id自动排序,写在_res判断下面
    1. shopCarList.value.sort((a,b) => {})

getProductsList方法最好使用async和await语法,而不是等价的.then。因为async和await语法不涉及大量的回调函数,也就不用进行大量的回调函数嵌套,处理起来更简单不容易出错。

//初始化商品列表数据的方法
  const getProductList = async () => {
    const res = await getProducts();
    productList.value = res;
  };
  // const getProductList = () => {
  //   getProducts().then((res) => {
  //     productList.value = res;
  //   });
  // };
  1. 写普通的table计算shopCarList里的商品总价
    1. 使用computed计算属性计算商品总价。
    2. const一个totalPrice
const useShoppingCarStore = defineStore("shopping-car", () => {
  //初始化商品列表数据
......
  //计算shopcarList里的商品总价
  const totalPrice = computed(() => {
    //reduce
    return shopCarList.value.reduce((pre, cur) => {
      return pre + cur.number * cur.price;
    }, 0);
  });
  .....
  return {...totalPrice,...};
});
    1. return一个reduce方法,它是一个数组遍历中常用的方法。第一个参数为回调逻辑,第二个参数为累加初始值(大多数为0)

    2. 把商品总价渲染到页面
  1. 在商品列表页写一个结算商品的button,
    1. 绑定点击事件calc(vue2不能直接绑click,需要加字符;vue3的组件绑定会判断是否为原生事件)
    2. 在store中写calc方法
    3. 结算方法已经写在products中,引入到store中。
    4. 该方法通过一个随机数来随机判断结算是否成功。、
    5. 这是一个异步方法,需要async和await
    6. 判断结算是否成功,成功弹出成功,并清空数组;
    7. 结算失败弹出失败,不清空列表,需要再次结算。
const useShoppingCarStore = defineStore("shopping-car", () => {
 ......
  //结算商品列表的方法
  const calc = async () => {
    const res = await buyProducts();
    if (res) {
      ElMessage.success({
        message: "结算成功",
        duration: 1000,
      });
      shopCarList.value = [];
    } else {
      ElMessage.error({
        message: "结算失败",
        duration: 1000,
      });
    }
  };
  return {
    ....
    calc,
  };
});
  1. 购物车中,对结算框v-if判断,如果购物车列表没有数据,则不显示结算框。
<template>
  <div class="shopping-car">
    <el-table :data="shoppingCarStore.shopCarList">
      <el-table-column prop="id" label="序号" align="center" />
      <el-table-column prop="title" label="名称" align="center" />
      <el-table-column prop="price" label="价格" align="center" />
      <el-table-column prop="number" label="数量" align="center" />
    </el-table>
    <div class="btn" v-if="shoppingCarStore.shopCarList.length">
      <h2>商品总价是:{{ shoppingCarStore.totalPrice }}</h2>
      <el-button type="primary" @click="calc">结算商品</el-button>
    </div>
  </div>
</template>

<script setup>
import { useShoppingCarStore } from "../store";
const shoppingCarStore = useShoppingCarStore();
function calc() {
  //触发商品结算的方法 calc()
  shoppingCarStore.calc();
}
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值