综合案例:使用vuex对购物车的商品数量和价格等公共数据进行状态管理

文章目录

        • 0.实现需求
        • 1.新建购物车模块cart
        • 2.使用json-server模拟向后端请求数据
        • 3.在vuex请求获取并存入数据,并映射到组件中,在组件中渲染【重点】
          • 3.1.安装axios
          • 3.2.准备actions和mutations,获取和存入数据到vuex中
          • 3.3.动态渲染:先用mapState映射list到组件页面
        • 4.点击修改数量并同步前后端【重点】
          • 4.1.要求和思路
          • 4.2.代码
        • 5.使用getters完成总价和总数量数据的同步
          • 5.1.先提供CartFooter.vue的结构和样式
          • 5.2.提供getters
          • 5.3. 使用getters
        • 其他
          • 1.为什么在axios在项目中要局部安装
          • 2.Axios PATCH 方法的功能与使用

0.实现需求
  • 请求动态渲染购物车,数据存放在vuex中
  • 使用数字框修改数据
  • 动态计算总价和总数量

购物车的商品数量,商品价格以及下方的总价,总数量,是共用一个数据,
显然,此处可以用到vuex,这也是Vuex在Vue项目中常见的使用场景之一

1.新建购物车模块cart
  • step1:新建store/modules/cart.js
export default{namespaced:true,//state写成这种形式的原因和data一样:保证组件实例化后的数据独立state(){//上面就不要const state={}了,会报错return{list:[]}}
}
  • step2:挂载到vuex仓库上
import cart from "@/store/modules/cart"
const store = new Vue.Store({modules:{cart}
})

验证配置是否成功:控制台>vue>Root>cart>namespaced

2.使用json-server模拟向后端请求数据
  • 安装json-server
npm install json-server -g
  • 准备json数据

在vue根目录下创建db/db.json(数据可以让deepseek模拟)

{"cart": [{"id": 1,"name": "Wireless Keyboard","price": 49.99,"count": 2,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"},{"id": 2,"name": "Gaming Mouse","price": 59.99,"count": 1,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"},{"id": 3,"name": "External Hard Drive","price": 89.99,"count": 1,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"},{"id": 4,"name": "Bluetooth Speaker","price": 79.99,"count": 1,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"},{"id": 5,"name": "Smartphone Case","price": 19.99,"count": 3,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"},{"id": 6,"name": "Laptop Backpack","price": 39.99,"count": 1,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"},{"id": 7,"name": "USB Flash Drive","price": 14.99,"count": 5,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"},{"id": 8,"name": "Headphones","price": 69.99,"count": 1,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"},{"id": 9,"name": "Monitor Stand","price": 29.99,"count": 1,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"},{"id": 10,"name": "Desk Lamp","price": 24.99,"count": 1,"thumb":"https://img14.360buyimg.com/n7/jfs/t1/141271/22/14881/70446/5fb4a985E1cce213e/beb55f6d1d3221b5.jpg"}],"friends": [{"userID": 101,"name": "Alice Johnson","age": 28},{"userID": 102,"name": "Bob Smith","age": 34},{"userID": 103,"name": "Charlie Brown","age": 22}]
}
  • 启动
在db目录下打开CMD:
json-server db.json

踩坑:遇到了端口号被占用的报错

\db>json-server db.json
node:internal/errors:478ErrorCaptureStackTrace(err);^
RangeError [ERR_SOCKET_BAD_PORT]: options.port should be >= 0 and < 65536. 

解决方法:指定端口号:json-server db.json --port:3008
在这里插入图片描述

3.在vuex请求获取并存入数据,并映射到组件中,在组件中渲染【重点】
3.1.安装axios
全局安装:npm install axios -g
局部安装:npm installl axios --save

踩坑:错误地使用了全局安装,导致在package.json中找不到axios依赖,也就调用不成功

3.2.准备actions和mutations,获取和存入数据到vuex中

过程:actions使用axios发起异步get请求获取数据,提交,触发mutations中的函数,该函数更新state的状态,
即:让空数组list存放返回的数据(res.data)

state:{return{list:[]}
},
mutations:{updateList(state,newList){state.list=newList}
},
actions:{async getData(context){const res=await axios.get("http:localhost:3008/cart");console.log(res);//查看res的层级结构context.commit("updateList",res.data);//提交,触发mutations中的方法}
}//在页面中调用:App.vue
created(){//格式:$store.dispatch("模块名/xxx")this.$store.dispatch("cart/getData")
}
3.3.动态渲染:先用mapState映射list到组件页面
//App.vuecomputed: {...mapState("cart", ["list"]),}

此时list已经获取后台json文件中的cart数组中的数据作为其元素,并通过mapState映射到组件中,
因此组件可以直接使用list进行页面渲染

//父组件App.vue
//使用v-for取出商品列表,但不在父组件直接渲染,而是设置自定义属性item,通过父传子,在子组件中渲染<div class="app-container"><cart-header></cart-header><cart-item v-for="item in list" :key="item.id" :item="item"></cart-item><cart-footer></cart-footer></div>
//子组件CartItem.vue
//html<div class="wrapper goods-container"><!-- 左侧图片 --><div class="left"><img :src="item.thumb" alt="" class="avatar"></div><!-- 右侧商品描述 --><div class="right"><!-- 标题 --><div class="title">{{item.name}}</div><div class="info"><!-- 单价 --><div class="price">¥{{item.price}}</div><!-- 按钮区域 --><div class="btns"><button class="btn btn-light" @click="btnClick(-1)">-</button><span class="count">{{item.count}}</span><button class="btn btn-light" @click="btnClick(1)">+</button></div></div></div></div>//js
//通过props属性接收父组件传过来的参数itemprops: {item:{type:Object,required:true}}//css(****不重要****)
.goods-container {display: flex;
}.left {flex: 1;padding: 10px;text-align: center;
}.right {flex: 2;padding: 10px;box-sizing: border-box;
}
.title {font-size: 16px;font-weight: bold;color: #333;margin-bottom: 10px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;
}
.price {font-size: 18px;color: #e4393c; /* 常见红色系表示优惠价 */margin-top: 5px;
}
.btns {margin-top: 15px;
}.btns button {display: inline-block;padding: 5px 10px;margin-right: 5px;font-size: 14px;cursor: pointer;border: none;border-radius: 3px;
}/* 不同类型的按钮样式 */
.btns .remove-btn {background-color: #ff4d4f;color: white;
}.btns .add-to-cart {background-color: #1abc9c;color: white;
}

效果:
在这里插入图片描述

4.点击修改数量并同步前后端【重点】
4.1.要求和思路

点击"+“和”-",实现数量的增减,要求不仅是vuex中的数据发生改变.后台json文件中也会同步修改
思路:

  • 按钮绑定点击事件,并传参,点击事件中会调用actions中的方法

  • actions中的方法主要做两件事:

    • 提交,触发mutations方法以更新vuex状态;
    • 使用axios.patch向后台发送请求,局部更新count属性
  • mutations中的方法根据匹配到的id,更新对应的count

4.2.代码
//CartItem.vue
//"+"和"-"按钮绑定btnClick
methods:{btnClick(num){const newCount=num+this.list.count;if(newCount<1) return;//商品数量不能少于1(商品数量为0或者删除商品的业务逻辑单独实现)count newId=this.list.id//调用actions方法:updateCountAsyncthis.$store.dispatch("cart/updateCountAsync",{newId,newCount})}
}//cart.js
mutations:{updateList(state,obj){//通过传回来的id找到对应的商品goodsconst goods=state.list.find(item==>item.id===obj.id);//更新这件商品的数量goods.count=obj.count;}
},
actions:{async updateCountAsync(context,obj){//更新后端数据const res=await axios.patch(`http://localhost:3008/cart/${obj.newId}`,{count:obj.newCount})console.log(res.data)//更新前端数据context.commit("updateList",{id:obj.newId,count:obj.newCount})}
}

效果:

  • 点击按钮"+",商品数量随之增加,控制台console.log(this.item.count)同步更新
  • 打开db.json文件,该商品的count属性被更新
5.使用getters完成总价和总数量数据的同步
5.1.先提供CartFooter.vue的结构和样式

如下:

<template><div class="footer-container"><!-- 中间的合计 --><div class="total-section"><span>共计xxx件商品,合计:</span><span class="price">¥xxx</span></div><!-- 右侧结算按钮 --><button class="btn btn-success btn-settle">结算</button></div>
</template><style scoped>
.footer-container {display: flex;justify-content: space-between;align-items: center;background-color: #f8f8f8;padding: 15px 20px;box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
}.total-section {font-size: 16px;color: #333;
}.total-section .price{font-size: 18px;color: #e60012; /* 使用醒目的颜色突出总价 */
}.btn-success {position: relative;display: inline-block;padding: 10px 20px;font-size: 16px;color: #ffffff;background-color: #e60012; /* 醒目红色背景 */border: none;border-radius: 5px;cursor: pointer;transition: all 0.3s ease-in-out;
}.btn-success:hover {background-color: darken(#e60012, 10%); /* 悬停时加深背景色 */transform: scale(1.05); /* 增加悬停效果 */
}
</style>
5.2.提供getters
	//格式:数组.reduce((求和参数,数组属性)=>xxx,0);//从0开始累计getters:{totalNum(state){return state.list.reduce((sum,item)=>sum+item.count,0)},totalPrice(state){return state.list.reduce((sum,item)=>sum+item.count*item.price,0)}}
5.3. 使用getters
//CartFooter.vue
//html
...<span>共计{{totalNum}}件商品,合计:</span><span class="price">¥{{totalPrice}}</span>//jsimport {mapGetters} from "vuex"...computed: {//格式:...mapGetters("子模块",['要映射的属性'])...mapGetters('cart',['totalNum','totalPrice'])
},

最终效果:
在这里插入图片描述

其他
1.为什么在axios在项目中要局部安装
1. 全局安装与局部安装的区别
当使用 npm install axios -g 进行全局安装时,Axios 被放置在系统的全局环境中,而不是当前项目的 node_modules 文件夹中。这意味着全局安装不会影响任何具体项目中的依赖列表,也不会更新该项目的 package.json 文件1。
因此,即使成功执行了 npm install axios -g,当前项目的 package.json 文件仍然不会有 axios 字段,这是预期行为而非错误。2. 导致模块未找到的根本原因
Vue 项目运行时,默认只会查找位于当前项目目录下的 node_modules 文件夹内的模块。如果 Axios 是通过 -g 参数全局安装的,则 Vue 构建工具(如 Webpack)无法识别该模块,从而引发 Module not found: Error: Can't resolve 'axios' 错误33. 正确的解决方案
为了使 Axios 在项目中可用,应将其作为局部依赖安装到当前项目中,而不是采用全局安装的方式。以下是具体的解决步骤:
方法一:局部安装 AXIOS 并保存到依赖项
执行以下命令将 Axios 安装为项目的局部依赖,并自动更新 package.json 文件:
npm install axios --save
此操作会在 package.json 的 dependencies 字段中添加 Axios 条目,同时下载对应的模块到 node_modules 文件夹中。对于像 Axios 这样的库,通常建议始终将其作为局部依赖安装。这样不仅可以确保不同项目间互不影响,还能更方便地管理版本冲突问题
2.Axios PATCH 方法的功能与使用

功能
axios.patch() 是一种用于向服务器发送部分修改的数据的方法。它通常用来更新资源的部分属性,而不是替换整个资源。这种行为符合 RESTful API 设计原则中的“局部更新”概念

作用于后台数据的能力
通过 axios.patch() 发送的请求会携带需要更新的具体字段及其新值,到指定 URL 上对应的资源。
服务器接收到这些数据后,会对目标资源执行相应的更新操作,并返回更新后的状态或确认消息。
这种方式相比 PUT 更高效,因为它只传输变化的内容而非完整的对象

语法

axios.patch(url[, data[, config]])
  • url: (字符串) 表示要访问的目标地址。
  • data: (可选, 对象或其他序列化类型) 要传递给服务器的信息体。
  • config: (可选, 对象) 配置选项,比如超时时间、自定义头部等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/79975.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/79975.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《数据结构初阶》【顺序表 + 单链表 + 双向链表】

《数据结构初阶》【顺序表 单链表 顺序表】 前言&#xff1a;先聊些其他的东西&#xff01;&#xff01;&#xff01;什么是线性表&#xff1f;什么是顺序表&#xff1f;顺序表的种类有哪些&#xff1f; 什么是链表&#xff1f;链表的种类有哪些&#xff1f; ---------------…

Android Retrofit框架分析(三):自动切换回主线程;bulid的过程;create方法+ServiceMethod源码了解

目录 Okhttp有什么不好&#xff1f;bulid的过程create方法ServiceMethodcall enqueue的过程为什么要学习源码呢&#xff1f; 一、Okhttp有什么不好&#xff1f; Okhttp本身来说&#xff0c;是一个挺好的网络框架&#xff0c;但&#xff0c;对于开发者而言&#xff0c;使用起…

C++ STL 基础与多线程安全性说明文档

C STL 基础与多线程安全性说明文档 一、STL 简介 STL&#xff08;Standard Template Library&#xff0c;标准模板库&#xff09;是 C 标准库的重要组成部分&#xff0c;提供了常用的数据结构和算法的泛型实现&#xff0c;极大地提高了代码的复用性和开发效率。 STL 的六大组…

数据结构之图的分类和存储

图 图(Graph)G由两个集合V和E组成&#xff0c;记为&#xff1a;G(V,E)&#xff0c;其中V是顶点的有穷非空集合(其实就是顶点)&#xff0c;E是V 中顶点偶对的有穷集合(就是边)。V(G)和E(G)通常分别表示图G的顶点集合以及边集合&#xff0c;E(G)可以为空集合&#xff0c;但是此时…

扩增子分析|微生物生态网络稳定性评估之鲁棒性(Robustness)和易损性(Vulnerability)在R中实现

一、引言 周集中老师团队于2021年在Nature climate change发表的文章&#xff0c;阐述了网络稳定性评估的原理算法&#xff0c;并提供了完整的代码。自此对微生物生态网络的评估具有更全面的指标&#xff0c;自此网络稳定性的评估广受大家欢迎。本系列将介绍网络稳定性之鲁棒性…

setup 函数在 Vue 3 中的作用是什么?什么时候会执行

文章目录 前言✅ 一、setup() 函数的作用是什么&#xff1f;✅ 二、setup() 什么时候执行&#xff1f;✅ 三、setup() 的参数✅ 四、setup() 中不能做什么&#xff1f;✅ 五、常见用法示例✅ 六、总结&#xff08;适合背诵或面试回答&#xff09; <script setup> 是 **Vu…

JDBC实现--保姆级教程~

本来以为写过一个使用python与数据库连接的文章&#xff0c;但是今天突然发现没有&#xff0c;那就直接写Java与数据库连接的吧。当然如果大家有需要可以告诉我&#xff0c;有时间的话也可以写一个的pymysql的使用的。 数据库有很多种&#xff0c;接下来我就以MySQL为例来进行讲…

Ubuntu18.04搭建samda服务器

一.什么是Samba服务器&#xff1f; Samba服务器是一种基于开源协议实现的网络共享服务软件&#xff0c;主要用于在不同操作系统&#xff08;如Windows、Linux、Unix&#xff09;之间实现文件和打印机共享功能。其核心目标是解决跨平台资源共享的兼容性问题&#xff0c;尤其是在…

《分词算法大揭秘:BPE、BBPE、WordPiece、ULM常见方法介绍》

分词算法是自然语言处理&#xff08;NLP&#xff09;中的一个重要预处理步骤&#xff0c;它将文本分割成更小的单元&#xff08;如单词、子词或字符&#xff09;。以下是几种常见的分词算法&#xff1a;Byte Pair Encoding (BPE)、Byte-level BPE (BBPE)、WordPiece 和 Unigram…

WordPress01 - 后台常用功能

最近些日子研究Wordpress&#xff0c;做些简单的笔记。 怎么安装Wordpress&#xff0c;怎么进的后台&#xff0c;这些咱就不唠了哈&#xff0c;网上到处是教程。 目录 1&#xff0c;Wordpress的后台 1-1&#xff0c; Posts(投稿) 1-2&#xff0c;Media(媒体) 1-3&#xf…

R8周:RNN实现阿尔茨海默病诊断

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 一、前期准备 1.设置GPU import numpy as np import pandas as pd import torch from torch import nn import torch.nn as nn import torch.nn.functi…

今天python练习题

目录 一、每日一言 二、练习题 三、效果展示 四、下次题目 五、总结 一、每日一言 不要害怕失败&#xff0c;失败可能成为我们前进的动力&#xff01; 二、练习题 有列表lst [[1,2,3],[4,5,6],[7,8,9]],取出其中的元素1/5/9组成新的列表 # 有列表lst [[1,2,3],[4,5,6],[…

机器人强化学习入门学习笔记(二)

基于上一篇的《机器人强化学习入门学习笔记》,在基于 MuJoCo 的仿真强化学习训练中,除了 PPO(Proximal Policy Optimization)之外,还有多个主流强化学习算法可用于训练机器人直行或其他复杂动作。 🧠 一、常见强化学习算法对比(可用于 MuJoCo) 算法类型特点适合场景PP…

用 DuckDB 高效分析 JSON 数据:从入门到实战

解析 JSON 文件进行分析常常充满挑战。无论你是在处理 API 响应、日志文件&#xff0c;还是应用数据&#xff0c;如果没有合适的工具&#xff0c;分析 JSON 都会非常耗时。 借助 DuckDB&#xff0c;你可以直接用 SQL 查询复杂的 JSON 文件&#xff0c;无需编写复杂的解析代码或…

从贴牌到品牌:出海官网如何让中国制造“贵”起来?

在全球经济一体化的当下&#xff0c;中美关税战如同一记重锤&#xff0c;给国际贸易格局带来了巨大震荡。自贸易摩擦爆发以来&#xff0c;双方多次调整关税政策&#xff0c;涉及的商品种类不断增多&#xff0c;税率持续攀升&#xff0c;众多中国企业的出口业务遭受重创&#xf…

react-13react中外部css引入以及style内联样式(动态className与动态style)

1. 外部css文件 - 普通引入 1.1 创建一个 CSS 文件&#xff0c;MyComponent.css。 /* MyComponent.css */ .my-class {color: red;font-size: 20px; } 1.2 组件中import引入 import React from react; import ./MyComponent.css; // 引入 CSS 文件function MyComponent() {r…

n8n 与智能体构建:开发自动化 AI 作业的基础平台

n8n 是一款开源的自动化流程构建平台&#xff0c;通过其模块化节点系统&#xff0c;开发者可以快速实现跨平台的任务编排、数据集成与智能交互。当 n8n 与大型语言模型&#xff08;LLM&#xff09;结合时&#xff0c;就能构建出具备感知、推理、执行能力的 AI 智能体&#xff0…

14.Spring Boot 3.1.5 集成 Spring Security 进行访问控制

14.Spring Boot 3.1.5 集成 Spring Security 进行访问控制 Spring Security 是一个强大且高度可定制的认证和访问控制框架&#xff0c;专为基于 Spring 的应用程序设计。它为基于 Java EE 的企业应用程序提供了全面的安全解决方案&#xff0c;包括 Web 应用程序安全和方法级安…

Linux学习笔记(二):Linux权限管理

文章目录 一、Linux下用户的分类1. Linux下用户分为两类&#xff1a;2. 这两类用户如何进行切换呢&#xff1f;3. 短暂提权 二、何为权限1. 什么是权限2. Linux的文件后缀意义 三、修改权限1. 设置文件的访问权限——chmod2. 修改文件拥有者——chown3. 修改文件所属组——chgr…

学习alpha,第2个alpha

alphas (-1 * ts_corr(rank(ts_delta(log(volume), 2)), rank(((close - open) / open)), 6)) 先分析操作符从左到右 ts_corr: Pearson 相关度量两个变量之间的线性关系。当变量呈正态分布且关系呈线性时&#xff0c;它最有效。 ts_corr(vwap, close, 20)是一个计算时间序列相…