当前位置: 首页 > news >正文

08.智慧商城——购物车布局、全选反选、功能实现

01. 购物车 - 静态布局

在这里插入图片描述

  1. 基本结构
<template><div class="cart"><van-nav-bar title="购物车" fixed /><!-- 购物车开头 --><div class="cart-title"><span class="all"><i>4</i>件商品</span><span class="edit"><van-icon name="edit" />编辑</span></div><!-- 购物车列表 --><div class="cart-list"><div class="cart-item" v-for="item in 10" :key="item"><van-checkbox></van-checkbox><div class="show"><img src="http://cba.itlike.com/public/uploads/10001/20230321/a072ef0eef1648a5c4eae81fad1b7583.jpg" alt=""></div><div class="info"><span class="tit text-ellipsis-2">新Pad 14英寸 12+128 远峰蓝 M6平板电脑 智能安卓娱乐十核游戏学习二合一 低蓝光护眼超清4K全面三星屏5GWIFI全网通 蓝魔快本平板</span><span class="bottom"><div class="price">¥ <span>1247.04</span></div><div class="count-box"><button class="minus">-</button><input class="inp" :value="4" type="text" readonly><button class="add">+</button></div></span></div></div></div><div class="footer-fixed"><div  class="all-check"><van-checkbox  icon-size="18"></van-checkbox>全选</div><div class="all-total"><div class="price"><span>合计:</span><span>¥ <i class="totalPrice">99.99</i></span></div><div v-if="true" class="goPay">结算(5)</div><div v-else class="delete">删除</div></div></div></div>
</template><script>
export default {name: 'CartPage'
}
</script><style lang="less" scoped>
// 主题 padding
.cart {padding-top: 46px;padding-bottom: 100px;background-color: #f5f5f5;min-height: 100vh;.cart-title {height: 40px;display: flex;justify-content: space-between;align-items: center;padding: 0 10px;font-size: 14px;.all {i {font-style: normal;margin: 0 2px;color: #fa2209;font-size: 16px;}}.edit {.van-icon {font-size: 18px;}}}.cart-item {margin: 0 10px 10px 10px;padding: 10px;display: flex;justify-content: space-between;background-color: #ffffff;border-radius: 5px;.show img {width: 100px;height: 100px;}.info {width: 210px;padding: 10px 5px;font-size: 14px;display: flex;flex-direction: column;justify-content: space-between;.bottom {display: flex;justify-content: space-between;.price {display: flex;align-items: flex-end;color: #fa2209;font-size: 12px;span {font-size: 16px;}}.count-box {display: flex;width: 110px;.add,.minus {width: 30px;height: 30px;outline: none;border: none;}.inp {width: 40px;height: 30px;outline: none;border: none;background-color: #efefef;text-align: center;margin: 0 5px;}}}}}
}.footer-fixed {position: fixed;left: 0;bottom: 50px;height: 50px;width: 100%;border-bottom: 1px solid #ccc;background-color: #fff;display: flex;justify-content: space-between;align-items: center;padding: 0 10px;.all-check {display: flex;align-items: center;.van-checkbox {margin-right: 5px;}}.all-total {display: flex;line-height: 36px;.price {font-size: 14px;margin-right: 10px;.totalPrice {color: #fa2209;font-size: 18px;font-style: normal;}}.goPay, .delete {min-width: 100px;height: 36px;line-height: 36px;text-align: center;background-color: #fa2f21;color: #fff;border-radius: 18px;&.disabled {background-color: #ff9779;}}}}
</style>
  1. 按需导入组件
import { Checkbox } from 'vant'
Vue.use(Checkbox)

02. 购物车 - 构建 vuex 模块 - 获取数据存储

  1. 新建 modules/cart.js 模块
export default {namespaced: true,state () {return {cartList: []}},mutations: {},actions: {},getters: {}
}
  1. 挂载到 store 上面
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import cart from './modules/cart'Vue.use(Vuex)export default new Vuex.Store({getters: {token: state => state.user.userInfo.token},modules: {user,cart}
})
  1. 封装 API 接口 api/cart.js
// 获取购物车列表数据
export const getCartList = () => {return request.get('/cart/list')
}
  1. 封装 action 和 mutation
mutations: {setCartList (state, newList) {state.cartList = newList},
},
actions: {async getCartAction (context) {const { data } = await getCartList()data.list.forEach(item => {item.isChecked = true})context.commit('setCartList', data.list)}
},
  1. 页面中 dispatch 调用
computed: {isLogin () {return this.$store.getters.token}
},
created () {if (this.isLogin) {this.$store.dispatch('cart/getCartAction')}
},

03. 购物车 - mapState - 渲染购物车列表

  1. 将数据映射到页面
import { mapState } from 'vuex'computed: {...mapState('cart', ['cartList'])
}
  1. 动态渲染
<!-- 购物车列表 -->
<div class="cart-list"><div class="cart-item" v-for="item in cartList" :key="item.goods_id"><van-checkbox icon-size="18" :value="item.isChecked"></van-checkbox><div class="show" @click="$router.push(`/prodetail/${item.goods_id}`)"><img :src="item.goods.goods_image" alt=""></div><div class="info"><span class="tit text-ellipsis-2">{{ item.goods.goods_name }}</span><span class="bottom"><div class="price">¥ <span>{{ item.goods.goods_price_min }}</span></div><CountBox :value="item.goods_num"></CountBox></span></div></div>
</div>

04. 购物车 - 封装 getters - 动态计算展示

  1. 封装 getters:商品总数 / 选中的商品列表 / 选中的商品总数 / 选中的商品总价
getters: {cartTotal (state) {return state.cartList.reduce((sum, item, index) => sum + item.goods_num, 0)},selCartList (state) {return state.cartList.filter(item => item.isChecked)},selCount (state, getters) {return getters.selCartList.reduce((sum, item, index) => sum + item.goods_num, 0)},selPrice (state, getters) {return getters.selCartList.reduce((sum, item, index) => {return sum + item.goods_num * item.goods.goods_price_min}, 0).toFixed(2)}
}
  1. 页面中 mapGetters 映射使用
computed: {...mapGetters('cart', ['cartTotal', 'selCount', 'selPrice']),
},<!-- 购物车开头 -->
<div class="cart-title"><span class="all"><i>{{ cartTotal || 0 }}</i>件商品</span><span class="edit"><van-icon name="edit"  />编辑</span>
</div><div class="footer-fixed"><div  class="all-check"><van-checkbox  icon-size="18"></van-checkbox>全选</div><div class="all-total"><div class="price"><span>合计:</span><span>¥ <i class="totalPrice">{{ selPrice }}</i></span></div><div v-if="true" :class="{ disabled: selCount === 0 }" class="goPay">结算({{ selCount }})</div><div v-else  :class="{ disabled: selCount === 0 }" class="delete">删除({{ selCount }})</div></div>
</div>

05. 购物车 - 全选反选功能

  1. 全选 getters
getters: {isAllChecked (state) {return state.cartList.every(item => item.isChecked)}
}...mapGetters('cart', ['isAllChecked']),<div class="all-check"><van-checkbox :value="isAllChecked" icon-size="18"></van-checkbox>全选
</div>
  1. 点击小选,修改状态
<van-checkbox @click="toggleCheck(item.goods_id)" ...></van-checkbox>toggleCheck (goodsId) {this.$store.commit('cart/toggleCheck', goodsId)
},mutations: {toggleCheck (state, goodsId) {const goods = state.cartList.find(item => item.goods_id === goodsId)goods.isChecked = !goods.isChecked},
}
  1. 点击全选,重置状态
<div @click="toggleAllCheck" class="all-check"><van-checkbox :value="isAllChecked" icon-size="18"></van-checkbox>全选
</div>toggleAllCheck () {this.$store.commit('cart/toggleAllCheck', !this.isAllChecked)
},mutations: {toggleAllCheck (state, flag) {state.cartList.forEach(item => {item.isChecked = flag})},
}

06. 购物车 - 数字框修改数量

  1. 封装 api 接口
// 更新购物车商品数量
export const changeCount = (goodsId, goodsNum, goodsSkuId) => {return request.post('/cart/update', {goodsId,goodsNum,goodsSkuId})
}
  1. 页面中注册点击事件,传递数据
<CountBox :value="item.goods_num" @input="value => changeCount(value, item.goods_id, item.goods_sku_id)"></CountBox>changeCount (value, goodsId, skuId) {this.$store.dispatch('cart/changeCountAction', {value,goodsId,skuId})
},
  1. 提供 action 发送请求, commit mutation
mutations: {changeCount (state, { goodsId, value }) {const obj = state.cartList.find(item => item.goods_id === goodsId)obj.goods_num = value}
},
actions: {async changeCountAction (context, obj) {const { goodsId, value, skuId } = objcontext.commit('changeCount', {goodsId,value})await changeCount(goodsId, value, skuId)},
}

07. 购物车 - 编辑切换状态

  1. data 提供数据, 定义是否在编辑删除的状态
data () {return {isEdit: false}
},
  1. 注册点击事件,修改状态
<span class="edit" @click="isEdit = !isEdit"><van-icon name="edit"  />编辑
</span>
  1. 底下按钮根据状态变化
<div v-if="!isEdit" :class="{ disabled: selCount === 0 }" class="goPay">去结算({{ selCount }})
</div>
<div v-else :class="{ disabled: selCount === 0 }" class="delete">删除</div>
  1. 监视编辑状态,动态控制复选框状态
watch: {isEdit (value) {if (value) {this.$store.commit('cart/toggleAllCheck', false)} else {this.$store.commit('cart/toggleAllCheck', true)}}
}

08. 购物车 - 删除功能完成

  1. 查看接口,封装 API ( 注意:此处 id 为获取回来的购物车数据的 id )
// 删除购物车
export const delSelect = (cartIds) => {return request.post('/cart/clear', {cartIds})
}
  1. 注册删除点击事件
<div v-else :class="{ disabled: selCount === 0 }" @click="handleDel" class="delete">删除({{ selCount }})
</div>async handleDel () {if (this.selCount === 0) returnawait this.$store.dispatch('cart/delSelect')this.isEdit = false
},
  1. 提供 actions
actions: {// 删除购物车数据async delSelect (context) {const selCartList = context.getters.selCartListconst cartIds = selCartList.map(item => item.id)await delSelect(cartIds)Toast('删除成功')// 重新拉取最新的购物车数据 (重新渲染)context.dispatch('getCartAction')}
},

09. 购物车 - 空购物车处理

  1. 外面包个大盒子,添加 v-if 判断
<div class="cart-box" v-if="isLogin && cartList.length > 0"><!-- 购物车开头 --><div class="cart-title">...</div><!-- 购物车列表 --><div class="cart-list">...</div><div class="footer-fixed">...</div>
</div><div class="empty-cart" v-else><img src="@/assets/empty.png" alt=""><div class="tips">您的购物车是空的, 快去逛逛吧</div><div class="btn" @click="$router.push('/')">去逛逛</div>
</div>
  1. 相关样式
.empty-cart {padding: 80px 30px;img {width: 140px;height: 92px;display: block;margin: 0 auto;}.tips {text-align: center;color: #666;margin: 30px;}.btn {width: 110px;height: 32px;line-height: 32px;text-align: center;background-color: #fa2c20;border-radius: 16px;color: #fff;display: block;margin: 0 auto;}
}

相关文章:

08.智慧商城——购物车布局、全选反选、功能实现

01. 购物车 - 静态布局 基本结构 <template><div class"cart"><van-nav-bar title"购物车" fixed /><!-- 购物车开头 --><div class"cart-title"><span class"all">共<i>4</i>件商品…...

金属压块液压打包机比例阀放大器

液压打包机是机电一体化产品&#xff0c;主要由机械系统、液压控制系统、上料系统与动力系统等组成。整个打包过程由压包、回程、提箱、转箱、出包上行、出包下行、接包等辅助时间组成。市场上液压打包机主要分为卧式与立式两种&#xff0c;立式废纸打包机的体积比较小&#xf…...

python 自动化福音,30行代码手撸ddt模块

用 python 做过自动化的小伙伴&#xff0c;大多数都应该使用过 ddt 这个模块&#xff0c;不可否认 ddt 这个模块确实挺好用&#xff0c;可以自动根据用例数据&#xff0c;来生成测试用例&#xff0c;能够很方便的将测试数据和测试用例执行的逻辑进行分离。 接下来就带大家一起…...

基于GATK流程化进行SNP calling

在进行变异检测时&#xff0c;以群体基因组重测序数据为例&#xff0c;涉及到的个体基本都是上百个&#xff0c;而其中大多数流程均是重复的步骤。 本文将基于GATK进行SNP calling的流程写入循环&#xff0c;便于批量分析。 1 涉及变量 1.工作目录work_dir/ 2.参考基因组ref…...

【Java SE】如何解读Java的继承和多态的特性?

前言 什么是继承和多态&#xff0c;为什么被称为Java三大特性&#xff0c;这两大特性为我们程序员带来了什么影响呢&#xff1f;是让复杂的代码简化了&#xff0c;还是为程序员写代码提供了多样性呢&#xff1f;那让我们一起来揭开这层神秘的面纱吧&#xff01; 1.继承 1.1为…...

uniapp 手动调用form表单submit事件

背景&#xff1a; UI把提交的按钮弄成了图片&#xff0c;之前的button不能用了。 <button form-type"submit">搜索</button> 实现&#xff1a; html&#xff1a; 通过 this.$refs.fd 获取到form的vue对象。手动调用里面的_onSubmit()方法。 methods:…...

11月20日星期一今日早报简报微语报早读

11月20日星期一&#xff0c;农历十月初八&#xff0c;早报微语早读。 1、T1以3-0横扫WBG&#xff0c;拿下S13冠军&#xff01;Faker豪取第4冠&#xff1b; 2、天舟七号货运飞船已运抵文昌发射场&#xff0c;将于明年初发射&#xff1b; 3、“中韩之战”球票已经售罄&#xf…...

Unity中 Start和Awake的区别

Awake和Start在Unity中都是MonoBehaviour脚本中的生命周期函数 Awake函数在游戏对象首次被加载时调用&#xff0c;在游戏对象初始化之前调用。 start函数在游戏对象初始化完成后调用&#xff0c;在update第一次执行前调用。 这两个函数在其生命周期内都只会调用一次&#xf…...

进度条、git常见指令以及gdb的常用指令

进度条 进度条是笔者所接触的第一个更加贴近于系统的小玩意&#xff0c;主要是要理解回车、换行、换行回车和缓冲区的概念。 回车是回到当前行的第一个光标位置&#xff0c;换行是换到下一行但是光标还在原来的位置&#xff0c;换行回车就是键盘上面的回车键是回到下一行的第…...

ubuntu20编译安装pkg-config

从下载到安装的步骤如下: wget https://pkg-config.freedesktop.org/releases/pkg-config-0.29.tar.gztar -zxvf pkg-config-0.29.tar.gzcd pkg-config-0.29/./configure --with-internal-glibsudo makesudo make checksudo make install make过程中可能会遇到的问题&#x…...

奇富科技发布鸿蒙元服务1.0版本,打造鸿蒙生态金融科技全新体验

近日&#xff0c;奇富科技率先发布鸿蒙元服务1.0版本&#xff0c;成为首家融入鸿蒙生态的金融科技公司&#xff0c;为用户带来前所未有的数字生活体验。此次与华为终端云的全面合作&#xff0c;是两大行业领军者的深度融合&#xff0c;不仅实现技术的交融&#xff0c;更彰显两大…...

【Git学习一】初始化仓库git init的使用和提交git add与git commit的使用

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;Git等软件工具技术的使用 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要…...

Redux-状态管理组件

一、简介 react中的状态只属于某个组件。而Redux是一个全局管理js状态的架构&#xff0c;让组件通信更加容易。 之前是状态在所有组件间传递&#xff0c;而redux通过store来实现这个功能。 Redux特性&#xff1a; 1.Single source Of truth&#xff0c;通过store唯一维护状态…...

【bigo前端】egret中的对象池浅谈

本文首发于&#xff1a;https://github.com/bigo-frontend/blog/ 欢迎关注、转载。 egret是一款小游戏开发引擎&#xff0c;支持跨平台开发&#xff0c;之前使用这款引擎开发了一款捕鱼游戏&#xff0c;在这里简单聊下再egret中关于对象池的使用&#xff0c;虽然该引擎已经停止…...

用公式告诉你 现货黄金投资者要不要换策略?

看过笔者相关文章的朋友都知道&#xff0c;其实笔者是相当不鼓励投资者更改策略的。但这并不意味着&#xff0c;策略不能改或者换。之所以反对更改策略&#xff0c;是因为很多人对自己的策略还没上手&#xff0c;没了解清楚就急着换策略&#xff0c;这是没必要的。通过下面这个…...

系列六、多线程集合不安全

一、多线程List集合不安全 1.1、List集合不安全案例代码 /*** Author : 一叶浮萍归大海* Date: 2023/11/20 12:38* Description: 多线层环境下List集合不安全案例代码*/ public class NotSafeListMainApp {public static void main(String[] args) {List<String> list …...

MidJourney笔记(1)-入门

注册 MidJourney注册和使用方式,有点特别。在介绍注册之前,需要给大家先介绍Discord。 Discord是一家游戏聊天应用与社区,在国内用的人相对比较少,在国外用得比较多。 那MidJourney和Discord有什么关系呢? MidJourney是搭建在Discord上的一个人工智能程序,通过在Discord添…...

CRM系统定制开发价格

我们都知道&#xff0c;CRM系统对企业有着很大的帮助。但是市面上大多数CRM系统都是标准化的&#xff0c;无法满足那些产品线复杂&#xff0c;或者有着特殊需求的企业。这个时候&#xff0c;就需要对CRM系统进行二次开发。那么&#xff0c;CRM系统二次开发的价格是多少&#xf…...

Kubernetes实战(五)-pod之间网络请求实战

1 同namespace内pod网络请求 1.1 创建namespace ygq $ kubectl create namespace ygq namespace/ygq created 1.2 创建svc和deployment 在naemspace ygq下创建两个应用&#xff1a;nginx和nginx-test。 1.2.1 部署应用nginx $ cat nginx-svc.yaml apiVersion: v1 kind: …...

7年经验之谈 —— 如何高效的开展app的性能测试?

APP性能测试是什么 从网上查了一下&#xff0c;貌似也没什么特别的定义&#xff0c;我这边根据自己的经验给出一个自己的定义&#xff0c;如有巧合纯属雷同。 客户端性能测试就是&#xff0c;从业务和用户的角度出发&#xff0c;设计合理且有效的性能测试场景&#xff0c;制定…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...