Vue项目商品购物车前端本地缓存逻辑(适用H5/ipad/PC端)——前端实现购物车删除商品、购物车增减数量,清空购物车功能

news2024/12/22 22:21:30

一、需求

1、用户选择商品,自动回显在购物车列表中;
2、同个商品追加,购物车列表数量叠加;
3、开启赠送,选中的商品,在购物车中另增一条数据,且购物车列表价格显示为0;其实际价格在最后结算是优惠价格其值是`赠送数量*商品价格`4、页面刷新,之前添加的商品依然存在;重新选择商品,依然遵循同类商品数量叠加,新增商品追加在购物车最上面;
5、购物车手动叠加/减数量,在商品列表在选择商品可以实时更新;
6、购物车商品/赠品,单个移除;
7、清空购物车;

二、最终效果

在这里插入图片描述

三、实现逻辑

1、选择商品逻辑

1、获取本地缓存,查看是否存在购物车数据;
2、如果不存在——将点击选中的商品数据、排重且数量求和后、存到本地缓存中;
3、如果存在
        1、判断购物车数据中是否存在现在要加购的商品(使用数组方法find)
        2、存在该商品——将该商品的数量+1
        3、不存在该商品——与已有商品一起加入到本地缓存中

2、初始化(即刷新后)----初始化获取本地缓存的数据

 mounted() {
    this.cacheHandler()
  },
methods: {
	 // 获取缓存数据
    cacheHandler() {
 		// 获取所有数据
      if (localStorage.getItem('finallyCartList') && JSON.parse(localStorage.getItem('finallyCartList')).length > 0) {
        this.finallyCartList = JSON.parse(localStorage.getItem('finallyCartList'))
        this.shoppingCartActive = this.finallyCartList[0]
      }
	}
}

3、数量加减——用户增减商品数量,更新本地存储数据

4、删除——filter过滤已经删除的数据,更新本地存储数据

5、清空购物车——清空本地存储数据

6、选择商品关键代码:

 // 选择商品
    itemHandler(item) {
      const cartObj = JSON.parse(JSON.stringify(item))
      // 商品数量
      cartObj.shoppingNum = 1
      // 是否赠品
      cartObj.isPresenter = this.isPresenter
      // 配置购物车列表的唯一值
      cartObj.soleId = `${cartObj.id}${cartObj.isPresenter}`
      // 是否配送
      cartObj.isDistribution = false
      // 查看本地是否存在购物车数据
      const store = JSON.parse(localStorage.getItem('finallyCartList') || '[]')
      if (store.length > 0) {
        // 判断购物车数据中是否存在现在要加购的商品
        const currentInfo = store.find(el => {
          return el.soleId == cartObj.soleId
        })
        if (currentInfo) {
          // 存在数量叠加1
          currentInfo.shoppingNum = currentInfo.shoppingNum + 1
          this.finallyCartList = [...store]
        } else {
          // 不存在追加在购物车列表前面
          this.finallyCartList = [cartObj, ...store]
        }
      } else {
        /**
         * 不存在本地购物车数据逻辑
         */
        this.shoppingCartList.push(cartObj)
        const shoppingCartList = JSON.parse(JSON.stringify(this.shoppingCartList))
        // 排重且数量求和
        const result = shoppingCartList.reduce((init, currentValue) => {
          const leng = init.findIndex(cur => cur.soleId === currentValue.soleId)
          if (leng != -1) {
            init[leng].shoppingNum += currentValue.shoppingNum
          } else {
            init.push(currentValue)
          }
          return init
        }, [])
        this.finallyCartList = [...result]
      }
      // 把最终购物车列表数据缓存在本地
      localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))
      // 购物车列表选中项
      this.shoppingCartActive = this.finallyCartList[0]
      // 初始化获取缓存数据
      this.cacheHandler()
      // console.log('finallyCartList', this.finallyCartList)
    }

四、源码

export default {
  name: 'Checkstand',
  data() {
    return {
      shoppingCartList: [], // 购物车列表
      finallyCartList: [], // 最终购物车列表
      shoppingCartActive: {
        shoppingNum: 1
      }, // 购物车选中项
      isPresenter: false, // 是否赠送

      isDistribution: false // 是否配送
    }
  },
  computed: {
    // 优惠金额
    discountsAmount() {
      return this.finallyCartList.filter(val => val.isPresenter).reduce((retailPrice, currentStudent) => {
        return retailPrice + (currentStudent.shoppingNum * currentStudent.retailPrice)
      }, 0)
    },
    // 总金额
    totalAmount() {
      return this.finallyCartList.filter(val => !val.isPresenter).reduce((retailPrice, currentStudent) => {
        return retailPrice + (currentStudent.shoppingNum * currentStudent.retailPrice)
      }, 0)
    }
  },
  mounted() {
    this.cacheHandler()
  },
  methods: {
    // 获取缓存数据
    cacheHandler() {
      // 获取所有数据
      if (localStorage.getItem('finallyCartList') && JSON.parse(localStorage.getItem('finallyCartList')).length > 0) {
        this.finallyCartList = JSON.parse(localStorage.getItem('finallyCartList'))
        this.shoppingCartActive = this.finallyCartList[0]
      }
    },
    // 点击购物车商品
    activeHandler(item) {
      this.shoppingCartActive = item
    },
    // 选择商品
    itemHandler(item) {
      const cartObj = JSON.parse(JSON.stringify(item))
      // 商品数量
      cartObj.shoppingNum = 1
      // 是否赠品
      cartObj.isPresenter = this.isPresenter
      // 配置购物车列表的唯一值
      cartObj.soleId = `${cartObj.id}${cartObj.isPresenter}`
      // 是否配送
      cartObj.isDistribution = false
      // 查看本地是否存在购物车数据
      const store = JSON.parse(localStorage.getItem('finallyCartList') || '[]')
      if (store.length > 0) {
        // 判断购物车数据中是否存在现在要加购的商品
        const currentInfo = store.find(el => {
          return el.soleId == cartObj.soleId
        })
        if (currentInfo) {
          // 存在数量叠加1
          currentInfo.shoppingNum = currentInfo.shoppingNum + 1
          this.finallyCartList = [...store]
        } else {
          // 不存在追加在购物车列表前面
          this.finallyCartList = [cartObj, ...store]
        }
      } else {
        /**
         * 不存在本地购物车数据逻辑
         */
        this.shoppingCartList.push(cartObj)
        const shoppingCartList = JSON.parse(JSON.stringify(this.shoppingCartList))
        // 排重且数量求和
        const result = shoppingCartList.reduce((init, currentValue) => {
          const leng = init.findIndex(cur => cur.soleId === currentValue.soleId)
          if (leng != -1) {
            init[leng].shoppingNum += currentValue.shoppingNum
          } else {
            init.push(currentValue)
          }
          return init
        }, [])
        this.finallyCartList = [...result]
      }
      // 把最终购物车列表数据缓存在本地
      localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))
      // 购物车列表选中项
      this.shoppingCartActive = this.finallyCartList[0]
      // 初始化获取缓存数据
      this.cacheHandler()
      // console.log('finallyCartList', this.finallyCartList)
    },
    // 清空购物车
    clearCart() {
      this.clearChche()
    },
    // 清空数据
    clearChche() {
      localStorage.setItem('finallyCartList', JSON.stringify([]))
      localStorage.setItem('showMemberObj', JSON.stringify({}))
      this.finallyCartList = []
      this.shoppingCartActive = {
        shoppingNum: 1
      }
      this.showMemberObj = { ticketCustomers: [] }
    },
    // 移除购物车商品
    delCommodity() {
      this.finallyCartList = this.finallyCartList.filter(val => this.shoppingCartActive.soleId !== val.soleId)
      localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))
      this.shoppingCartActive = this.finallyCartList[0] || { shoppingNum: 1 }
      this.cacheHandler()
    },
    // 配送选中事件
    changeDistribution(val) {
      if (!this.shoppingOrTicket) {
        Toast('请先选择会员!')
        return
      }
      this.finallyCartList.forEach(item => {
        if (item.id === this.shoppingCartActive.id) {
          item.isDistribution = val
        }
      })
      localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))
    },
    // 每次增减数量重置缓存
    plusminusHandle() {
      setTimeout(() => {
        localStorage.setItem('finallyCartList', JSON.stringify(this.finallyCartList))
      }, 300)
    },
    // 收款
    collection() {
      console.log('会员信息', this.showMemberObj)
      const params = {
        addressId: this.showMemberObj.addressId || 0,
        customerId: this.showMemberObj.customerId || 0,
        customerPhone: this.showMemberObj.customerPhone || '',
        address: this.showMemberObj.address || '',
        customerName: this.showMemberObj.customerName || '',
        operateType: 2,
        directDiscountAmount: 0,
        orderStatus: 0,
        amountReceivable: this.totalAmount,
        itemMessageDTOList: this.finallyCartList && this.finallyCartList.map(item => { return { itemCode: item.itemCode, qty: item.shoppingNum, itemGiftType: item.isPresenter ? 1 : 0, pickType: item.isDistribution ? 0 : 1 } })
      }
      console.log('收款最终参数--会员数据', params)
      // return
      this.$router.push({ path: '/settleAccounts', query: { data: JSON.stringify(params) } })
    }
  }
}

五、相关文章


Vue3 + Vite + Ts开源后台管理系统模板


基于ElementUi或AntdUI再次封装基础组件文档


基于Element-plus再次封装基础组件文档(vue3+ts)


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

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

相关文章

【OpenVINOSharp】在英特尔® 开发者套件爱克斯开发板使用OpenVinoSharp部署Yolov8模型

在英特尔 开发者套件爱克斯开发板使用OpenVinoSharp部署Yolov8模型 一、英特尔开发套件 AIxBoard 介绍1. 产品定位2. 产品参数3. AI推理单元 二、配置 .NET 环境1. 添加 Microsoft 包存储库2. 安装 SDK3. 测试安装4. 测试控制台项目 三、安装 OpenVINO Runtime1. 下载 OpenVINO…

【无闪烁AI视频制作】

效果查看: https://tianfeng.space/wp-content/uploads/2023/08/8月16日-12.mp4 前言 现在其实有很多的AI视频了,效果也越来越逼真,来看看都是怎么制作的吧! 安装 TemporalKit下载 https://github.com/CiaraStrawberry/Tempo…

STM32 F103C8T6学习笔记9:0.96寸单色OLED显示屏—自由取模显示—显示汉字与图片

今日学习0.96寸单色OLED显示屏的自由取模显示: 宋体汉字比较复杂,常用字符可以直接复制存下来,毕竟只有那么几十个字母字符,但汉字实在太多了,基本不会全部放在单片机里存着,一般用到多少个字就取几个字的模&#xff…

操作系统_内存管理(一)

目录 1. 内存管理 1.1 内存管理的概念 1.1.1 内存管理的基本原理和要求 1.1.1.1 程序的链接和装入 1.1.1.2 逻辑地址与物理地址 1.1.1.3 进程的内存映像 1.1.1.4 内存保护 1.1.1.5 内存共享 1.1.1.6 内存分配与回收 1.2 覆盖与交换 1.2.1 覆盖 1.2.2 交换 1.3 连续…

华为认证为什么现在这么受欢迎?

华为认证目前受欢迎的原因有很多,以下是其中一些主要原因: 高质量的认证培训:华为认证提供了一系列高质量的培训课程,涵盖了IT技术、网络安全、云计算等领域。这些培训课程由华为的技术专家和工程师团队设计和提供,内容…

Openlayers 实战 - 地图视野(View)- 图层 -(layer)- 资源(source)显示等级设置

Openlayers 实战 - 地图视野(View)- 图层 -(layer)- 资源(source)显示等级设置 问题原因核心代码完整代码:在线示例 在以往的项目维护中,出现一个问题,使用最新高清底图发…

基于traccar快捷搭建gps轨迹应用

0. 环境 - win10 虚拟机ubuntu18 - i5 ubuntu22笔记本 - USB-GPS模块一台,比如华大北斗TAU1312-232板 - 双笔记本组网设备:路由器,使得win10笔记本ip:192.168.123.x,而i5笔记本IP是192.168.123.215。 - 安卓 手机 1.…

PHP酒店点菜管理系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 酒店点菜管理系统是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 代码下载 https://download.csdn.net/download/qq_41221322/88232051 论文 https://…

ARM体系结构学习笔记:NZCV

NZCV N: negative 算术逻辑运算单元运算结果为负1/正0 Z: zero 算术逻辑运算单元运算结果为零1/非零0 C: 3cases:1 0加法 Carray | Not Carray减法 Not Borrow | Borrow(Not Carray)移位 Bit Shifted | Rotated Out V: 后面详细阐述[外…

【C语言】数组概述

🚩纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:C语言 🔥该篇将带你了解 一维数组,二维数组等相关知识。 目录: 📘前言:&#x1f…

【探索Linux】—— 强大的命令行工具 P.6(调试器-gdb、项目自动化构建工具-make/Makefile)

阅读导航 前言一、什么是调试器二、详解 GDB - 调试器1.使用前提2.经常使用的命令3.使用小技巧 三、项目自动化构建工具 - make/Makefile1. make命令⭕语法⭕常用选项⭕常用操作⭕make命令的工作原理⭕make命令的优势: 2.Makefile文件⭕Makefile的基本结构⭕Makefil…

jvm-运行时数据区概述及线程

1.运行时数据区内部结构 不同的jvm对于内存的划分方式和管理机制存在着部分差异 java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机的启动而创建,随着虚拟机的退出而销毁,另外一些则是与线程一一对应的&…

过来,我告诉你个秘密:送给程序员男友最好的礼物,快教你对象学习磁盘分区啦!小点声哈,别让其他人学会了!

[原文连接:来自给点知识](过来,我告诉你个秘密:送给程序员男友最好的礼物,快教你对象学习磁盘分区啦!小点声哈,别让其他人学会了!) 再唱不出那样的歌曲 听到都会红着脸躲避 虽然会经常忘了我依然爱着你 …

linux学习(文件描述符)[13]

所以fork的时候函数执行完毕,但是数据还在缓冲区中未刷新。 所以会有父子两份数据 在fork()之前ffush()(c语言的接口,刷新缓冲区)fflush(stdout),就不会有重复 缓冲区的…

公网远程连接Redis数据库详解

文章目录 1. Linux(centos8)安装redis数据库2. 配置redis数据库3. 内网穿透3.1 安装cpolar内网穿透3.2 创建隧道映射本地端口 4. 配置固定TCP端口地址4.1 保留一个固定tcp地址4.2 配置固定TCP地址4.3 使用固定的tcp地址连接 前言 洁洁的个人主页 我就问你有没有发挥&#xff0…

动态loading中转页

动态loading中转页 template <div class"loading"><div class"wavy"><!-- --i是自定义属性&#xff0c;可通过var函数调用 --><span style"--i: 1">登</span><span style"--i: 2">录</span>…

银行数据分析师面试题

回答&#xff1a; 1.自我介绍&#xff1a; "大家好&#xff0c;我是XXX&#xff0c;一名数据分析师。我有着对数据的热爱和深入的了解&#xff0c; 希望能够利用我的技能和知识为企业解决问题、做出有效的决策。 在过去的X年里&#xff0c;我一直从事数据分析相关的工作…

【福建事业单位-公基-法】02国家基本制度、公民的基本权利和义务 国家机构

【福建事业单位-公基-法】02国家基本制度 一、国家基本制度1.1 自然资源归属1.2 选举制度1.3 民族区域自治制度总结 二、公民的基本权利和义务1.1 权力1.2 义务总结 三、国家机构3.1 全国人民代表大会3.2全国人民代表大会常务委员会3.3 国家主席3.4国务院3.5监察委3.6 人民法院…

终于找到了这款最好的文献下载网站

在我们文献资源匮乏时&#xff0c;查找下载文献是件非常困难的事。在网上搜索了许多文献下载网站&#xff0c;不是文献资源太少&#xff0c;就是性价比太低&#xff0c;经过筛检比对终于找到了这款文献资源既丰富&#xff0c;又经济适用的文献下载网站。 这款文献下载网站就是…

6.Web后端开发【SpringBoot入门】

文章目录 1 SpringBoot快速入门1.1 Web分析 2. HTTP协议2.1 HTTP-概述2.1.1 介绍2.2.2 特点 2.2 HTTP-请求协议2.3 HTTP-响应协议2.3.1 格式介绍2.3.2 响应状态码 常见的相应状态码 3 WEB服务器3.1 服务器概述 1 SpringBoot快速入门 Spring的官网Spring Boot 可以帮助我们非常…