Day46:项目-购物车案例
购物车案例
- 准备工作
-
- 首页默认加载,其余页面懒加载

- 调用defineStore方法构建store

- 入口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");
-
- api就是用来模拟后台接口的

- api就是用来模拟后台接口的
- 在app.vue中做购物车首页,头部不进入路由,在头部的底部放RouterView
- 给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>
-
- 写购物车首页的标题
- 写el-button:商品列表,购物车。并用routerLink包裹,做一个导航,并为RouterLink添加to页面
- 在商品列表页面,写一个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>
- 在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([]);
-
- 一秒钟之后获取到数据(模拟从接口获取数据),
//1s中之后返回数组数据
export const getProducts = async ()=>{//为了模拟真实的接口请求await wait(1000)return products
}
-
- 方法在数据获取的部分有定义。
- 把两个需要给视图使用的方法从store中导出,并在商品列表中导入方法
- 绑定在table中,
- 给table添加按钮
-
- 改变button样式
- 绑定add方法,在页面中传参scope.row,代表点选的那一行。(scope代表插槽的作用域)在方法中传参row
<script setup>
import { useShoppingCarStore } from "../store";
const shoppingCarStore = useShoppingCarStore();
shoppingCarStore.getProductList();
function add(row) {//调用 将数据添加到购物车的方法shoppingCarStore.addShopCarList(row);
}
</script>
- 在store中写给购物车添加数据的方法
-
- 减去商品列表页面的库存:res的item id === row id时,下转判断,判断完自减--
- 添加购物车列表页面的商品数量,_res的item id === row id时,下转判断
-
-
- 在store中定义初始化购物车列表
- 判断购物车中是否已经存在这个商品
- 如果存在,将商品数量+1(_res.number++
- 如果没有,添加一个新商品(起始数量一定是1
-
-
- 判断当库存<1,写一个提示,商品已经妹有了,存在一秒。
- 导出方法并在列表页调用,放在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,...};
- 在购物车列表中写el-table
-
- 引入useshoppingcarstore,并绑定数据.shopCarList
- 绑定prop属性,表示绑定了哪个属性
- 在store中添加排序功能,商品加入购物车后按照id自动排序,写在_res判断下面
-
- 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;// });// };
- 写普通的table计算shopCarList里的商品总价
-
- 使用computed计算属性计算商品总价。
- const一个totalPrice
const useShoppingCarStore = defineStore("shopping-car", () => {//初始化商品列表数据
......//计算shopcarList里的商品总价const totalPrice = computed(() => {//reducereturn shopCarList.value.reduce((pre, cur) => {return pre + cur.number * cur.price;}, 0);});.....return {...totalPrice,...};
});
-
- return一个reduce方法,它是一个数组遍历中常用的方法。第一个参数为回调逻辑,第二个参数为累加初始值(大多数为0)

- 把商品总价渲染到页面
- return一个reduce方法,它是一个数组遍历中常用的方法。第一个参数为回调逻辑,第二个参数为累加初始值(大多数为0)
- 在商品列表页写一个结算商品的button,
-
- 绑定点击事件calc(vue2不能直接绑click,需要加字符;vue3的组件绑定会判断是否为原生事件)
- 在store中写calc方法
- 结算方法已经写在products中,引入到store中。
- 该方法通过一个随机数来随机判断结算是否成功。、
- 这是一个异步方法,需要async和await
- 判断结算是否成功,成功弹出成功,并清空数组;
- 结算失败弹出失败,不清空列表,需要再次结算。
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,};
});
- 购物车中,对结算框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>相关文章:
Day46:项目-购物车案例
购物车案例 准备工作 首页默认加载,其余页面懒加载 调用defineStore方法构建store 入口main做对应配置,找指南,快速开始,把elementplus引入进来 import { createApp } from "vue"; import { createPinia } from &qu…...
【小沐学CAD】嵌入式UI开发工具:GL Studio
文章目录 1、简介2、软件功能3、应用行业3.1 航空3.2 汽车3.3 防御3.4 工业3.5 电力与能源3.6 医疗3.7 空间3.8 科技 结语 1、简介 https://disti.com/gl-studio/ DiSTI 是 HMI 软件、虚拟驾驶舱、仪表、信息娱乐、集群显示器和嵌入式 UI 解决方案的领先提供商。 而它的GL Stu…...
Python:Tornado框架之获取get和post的传参
一、获取get方式传参 import tornado.ioloop #导入tornado包 import tornado.web class MainHandle(tornado.web.RequestHandler):def get(self,id): #定义请求函数self.write("Hello %s!" %id)apptornado.web.Application([ #定义应用配置函数(r"/…...
JSON和全局异常处理
目录 1️⃣JSON 一、什么是json? 二、与javascript的关系 三、语法格式 四、注意事项 五、总结 六,使用json 1导入pom.xml依赖 2.配置spring-mvc.xml 3. ResponseBody注解使用 创建一个web层控制器 编写ClazzBiz 实现接口 测试: …...
骨传导耳机有害处吗、骨传导耳机真的不好用吗?
骨传导耳机没有害处。 骨传导耳机是通过将声音传递到颅骨,再由颅骨传递到内耳,从而达到听声音的效果,与传统的耳机不同。 因此,骨传导耳机不会直接对人的身体健康、耳朵产生压力和损伤,也不会影响耳道和中耳的正常功能…...
第一类曲面积分:曲面微元dσ与其投影面积微元dxdy之间的关系推导
第一类曲面积分:曲面微元dσ与其投影面积微元dxdy之间的关系推导 本篇博客精简自本人关于曲面积分的博客:详情见:曲面积分(Surface Integral) 曲面参数化(曲面上的每个点都使用起点为原点、终点为该曲面上的点的向量表示&#x…...
vue学习之Font Awesome图标
官方文档 https://fontawesome.com.cn/v5 Font Awesome 安装 cnpm install font-awesome/src/main.js 引入css import Vue from vue; import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; import App from ./App.vue;...
mysql内连接与外连接详解
内连接与外连接 内连接外连接 在数据库中,连接操作是一种把两个或者多个表的记录组合在一起的操作,常用的有内连接(Inner Join)、外连接(Outer Join)等。 内连接 内连接(Inner Join࿰…...
在Mujoco环境下详细实现PPO算法应用于Humanoid-v2的完整教程
第一部分:介绍 1. 背景介绍 MuJoCo,或称为多关节动力学与控制的物理引擎,已经成为了强化学习中仿真环境的首选工具。其精确的物理仿真和高效的速度使得研究者可以在这个环境下测试和验证各种算法。PPO,即近端策略优化,是一种深度强化学习中的策略优化方法。它解决了TRPO…...
怎么给网络加速
首先,按winr,调出运行窗口。 输入cmd,回车,再输入gpedit.msc,调出本地组策略编辑器。 点击计算机配置下的管理模版。 再点击网络。 再点击Qos数据包计划程序。 再点击限制可保留宽带。 选择已启用,再把带宽…...
golang for循环append的数据重复
原因,因为使用了& 需要增加一行,问题解决...
趣谈网络协议_1
趣谈网络协议_1 第1讲 | 为什么要学习网络协议?第4讲 | DHCP与PXE:IP是怎么来的,又是怎么没的?动态主机配置协议(DHCP) 第5讲 | 从物理层到MAC层:如何在宿舍里自己组网玩联机游戏?第…...
利用WebStorm开发react——本文来自AI创作助手
要在WebStorm中开发React应用程序,请按照以下步骤进行设置: 1.安装Node.js和npm(如果尚未安装)。 2.下载和安装WebStorm。 3.打开WebStorm,并在欢迎界面中选择“Create New Project”。 4.在弹出窗口中,…...
将本地构建的镜像推送到远程镜像库,构建多种系统架构支持的Docker镜像并推送到Docker Hub
目录 推送到 Docker Hub前提:需要在 [Docker Hub](https://hub.docker.com/) 创建账户、创建仓库。1. 创建 Dockerfile 和构建镜像:docker build -t2. 登录到远程镜像库:docker login3. 将镜像标记为远程仓库地址:docker tag4. 推…...
【技术分享】NetLogon于域内提权漏洞(CVE-2020-1472)
一、漏洞介绍 CVE-2020-1472是一个Windows域控中严重的远程权限提升漏洞。攻击者在通过NetLogon(MS-NRPC)协议与AD域控建立安全通道时,可利用该漏洞将AD域控的计算机账号密码置为空,从而控制域控服务器。该漏洞适用于Win2008及后…...
python学习之【模块】
前言 上一篇文章 python学习之【深拷贝】中学习了python中的深浅拷贝学习内容,这篇文章接着学习python中的模块。 什么是模块 在python中,一个文件(以“.py”为后缀名的文件)就叫做一个模块,每一个模块在python里都…...
dns电脑服务器发生故障怎么修复
DNS电脑服务器发生故障可能会导致网络连接问题、网页无法访问、或者电子邮件无法发送等情况。修复DNS电脑服务器故障可以采取多种方法,例如检查网络连接、更换DNS服务器等措施。当DNS电脑服务器发生故障时,可以采取以下修复措施: 尝试刷新DNS…...
Python项目Flask ipv6双栈支持改造
一、背景 Flask 是一个微型的(轻量)使用Python 语言开发的 WSGI Web 框架(一组库和模块),基于Werkzeug WSGI工具箱/库和Jinja2 模板引擎,当然,Python的WEB框架还有:Django、Tornado、Webpy,这暂且不提。 Flask使用BSD授权。 Flask也被称为microframework(微框架),F…...
hcia 目的mac为(单播 组播 广播)mac
从下往上看...
专栏十:10X单细胞的聚类树绘图
经常在文章中看到对细胞群进行聚类,以证明两个cluster之间的相关性,这里总结两种绘制这种图的方式和代码,当然我觉得这些五颜六色的颜色可能是后期加的,本帖子只总结画树状图的方法 例一 文章Single-cell analyses implicate ascites in remodeling the ecosystems of pr…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
