附录2-购物车案例

news2024/11/15 4:19:27

目录

1  效果

2  接口数据

3  App.vue

4  HEADER.vue

5  COUNT.vue

6  GOODS.vue

7  FOOTER.vue


1  效果

由四种子组件和一个App.vue构成

2  接口数据

返回结果如下

{
    "status": 200,
    "message": "获取购物车列表数据成功!",
    "list": [
        {
            "id": 1,
            "goods_name": "班俏BANQIAO超火ins潮卫衣女士2020秋季新款韩版宽松慵懒风薄款外套带帽上衣",
            "goods_img": "https://www.escook.cn/vuebase/pics/1.png",
            "goods_price": 108,
            "goods_count": 1,
            "goods_state": true
        },
        {
            "id": 2,
            "goods_name": "嘉叶希连帽卫衣女春秋薄款2020新款宽松bf韩版字母印花中长款外套ins潮",
            "goods_img": "https://www.escook.cn/vuebase/pics/2.png",
            "goods_price": 129,
            "goods_count": 1,
            "goods_state": true
        },
        {
            "id": 3,
            "goods_name": "思蜜怡2020休闲运动套装女春秋季新款时尚大码宽松长袖卫衣两件套",
            "goods_img": "https://www.escook.cn/vuebase/pics/3.png",
            "goods_price": 198,
            "goods_count": 1,
            "goods_state": false
        },
        {
            "id": 4,
            "goods_name": "思蜜怡卫衣女加绒加厚2020秋冬装新款韩版宽松上衣连帽中长款外套",
            "goods_img": "https://www.escook.cn/vuebase/pics/4.png",
            "goods_price": 99,
            "goods_count": 1,
            "goods_state": false
        },
        {
            "id": 5,
            "goods_name": "幂凝早秋季卫衣女春秋装韩版宽松中长款假两件上衣薄款ins盐系外套潮",
            "goods_img": "https://www.escook.cn/vuebase/pics/5.png",
            "goods_price": 156,
            "goods_count": 1,
            "goods_state": true
        },
        {
            "id": 6,
            "goods_name": "ME&CITY女装冬季新款针织抽绳休闲连帽卫衣女",
            "goods_img": "https://www.escook.cn/vuebase/pics/6.png",
            "goods_price": 142.8,
            "goods_count": 1,
            "goods_state": true
        },
        {
            "id": 7,
            "goods_name": "幂凝假两件女士卫衣秋冬女装2020年新款韩版宽松春秋季薄款ins潮外套",
            "goods_img": "https://www.escook.cn/vuebase/pics/7.png",
            "goods_price": 219,
            "goods_count": 2,
            "goods_state": true
        },
        {
            "id": 8,
            "goods_name": "依魅人2020休闲运动衣套装女秋季新款秋季韩版宽松卫衣 时尚两件套",
            "goods_img": "https://www.escook.cn/vuebase/pics/8.png",
            "goods_price": 178,
            "goods_count": 1,
            "goods_state": true
        },
        {
            "id": 9,
            "goods_name": "芷臻(zhizhen)加厚卫衣2020春秋季女长袖韩版宽松短款加绒春秋装连帽开衫外套冬",
            "goods_img": "https://www.escook.cn/vuebase/pics/9.png",
            "goods_price": 128,
            "goods_count": 1,
            "goods_state": false
        },
        {
            "id": 10,
            "goods_name": "Semir森马卫衣女冬装2019新款可爱甜美大撞色小清新连帽薄绒女士套头衫",
            "goods_img": "https://www.escook.cn/vuebase/pics/10.png",
            "goods_price": 153,
            "goods_count": 1,
            "goods_state": false
        }
    ]
}

3  App.vue

<template>
  <HEADER title="购物车案例"></HEADER>
  <div class="good_list">
    <GOODS
    v-for="item in good_list"
    :key="item.id"
    :goods_state_from_other="item.goods_state"
    :goods_img="item.goods_img"
    :goods_name="item.goods_name"
    :goods_price="item.goods_price"
    :goods_count="item.goods_count"
    :goods_id=item.id
    @get_son_state="change_one_check"
    ></GOODS>
  </div>
  <FOOTER
  :all_checked_from_other=all_checked
  :total_price=total_price
  :goods_total_num=goods_total_num
  @all_check="all_check"
  ></FOOTER>
  
</template>

<script>

import FOOTER from '@/components/FOOTER.vue'
import GOODS from '@/components/GOODS.vue'
import HEADER from '@/components/HEADER.vue'
import axios from 'axios'
import bus from '@/components/eventBus.js'

export default {
  name: 'App',
  components: {
    FOOTER,
    GOODS,
    HEADER
  },
  data() {
    return {
      good_list: [],
      all_checked:false,
      total_price:0,
      goods_total_num:0
    }
  },
  methods: {
    get_goods_list() {
      axios({
        method: 'GET',
        url: 'https://www.escook.cn/api/cart'
      }).then((res) => {
        if (res.data.status === 200) {
          this.good_list = res.data.list
          this.get_footer_infomation()
        }
        else {
          alert(res.data.message)
        }
      })
    },
    get_footer_infomation() {
      this.all_checked = this.good_list.every((item) => item.goods_state == true)
      this.goods_total_num = 0
      this.total_price = this.good_list.reduce((sum,item)=>{
        if (item.goods_state == true) {
          this.goods_total_num = this.goods_total_num + item.goods_count
          sum = sum + item.goods_price * item.goods_count
        }
        return sum
      },0)
    },
    all_check(val) {
      for (let i in this.good_list) {
        this.good_list[i].goods_state = val
      }
    },
    change_one_check(val) {
      console.log(val)
      for (let i in this.good_list) {
        if (this.good_list[i].id == val.goods_id) {
          this.good_list[i].goods_state = val.goods_state
        }
      }
    },
    change_one_count(val) {
      for (let i in this.good_list) {
        if (this.good_list[i].id == val.goods_id) {
          this.good_list[i].goods_count = val.goods_count
        }
      }
    }
  },
  created() {
    this.get_goods_list()
  },
  beforeUpdate() {
    this.get_footer_infomation()
    bus.$on('counter_send_to_App_goods_count_event',val => {
      this.change_one_count(val)
    })
  }
}
</script>

<style scoped>
.good_list {
  margin-top:45px;
  margin-bottom:50px;
}
</style>

传数据的时候最好不要将一个整个对象传过去,最好在传的时候就把对象拆散,这样你子组件的复用性会提高

4  HEADER.vue

<template>
  <div class="header-container">{{ title }}</div>
</template>

<script>
export default {
  props: {
    title:{
      type:String,
      default:'标题'
    }
  }
}
</script>

<style lang="less" scoped>
.header-container {
  font-size: 12px;
  height: 45px;
  width: 100%;
  background-color: #1d7bff;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  position: fixed;
  top: 0;
  left:0;
  z-index: 999;
}
</style>

5  COUNT.vue

COUNT.vue通过eventbus直接与App.uve通信

<template>
  <div class="number-container d-flex justify-content-center align-items-center">
    <!-- 减 1 的按钮 -->
    <button type="button" class="btn btn-light btn-sm" @click="change_num(-1)">-</button>
    <!-- 购买的数量 -->
    <span class="number-box">{{ goods_count }}</span>
    <!-- 加 1 的按钮 -->
    <button type="button" class="btn btn-light btn-sm" @click="change_num(1)">+</button>
  </div>
</template>

<script>
import bus from './eventBus.js'

export default{
  props:{
    goods_count_from_other: {
      type:Number,
      default:1
    },
    goods_id: {
      type:Number,
      required:true
    }
  },
  data() {
    return {
      goods_count:1
    }
  },
  created() {
    this.goods_count = this.goods_count_from_other
  },
  methods: {
    change_num(n) {
      if (n<0) {
        if (this.goods_count > 1) {
          this.goods_count = this.goods_count + n
        }
      }
      else {
        this.goods_count = this.goods_count + n
      }
      bus.$emit('counter_send_to_App_goods_count_event',{
        goods_count:this.goods_count,
        goods_id:this.goods_id
      })
    },
  },
}
</script>

<style lang="less" scoped>
.number-box {
  min-width: 30px;
  text-align: center;
  margin: 0 5px;
  font-size: 12px;
}

.btn-sm {
  width: 30px;
}
</style>

6  GOODS.vue

<template>
  <div class="goods-container">
    <!-- 左侧图片 -->
    <div class="thumb">
      <div class="custom-control custom-checkbox">
        <!-- 复选框 -->
        <input type="checkbox" class="custom-control-input" :id="'goods' + goods_id" v-model=goods_state />
        <label class="custom-control-label" :for="'goods' + goods_id">
          <!-- 商品的缩略图 -->
          <img :src=goods_img alt=''/>
        </label>
      </div>
    </div>
    <!-- 右侧信息区域 -->
    <div class="goods-info">
      <!-- 商品标题 -->
      <h6 class="goods-title">{{ goods_name }}</h6>
      <div class="goods-info-bottom">
        <!-- 商品价格 -->
        <span class="goods-price">¥{{ goods_price }}</span>
        <!-- 商品的数量 -->
        <COUNTER :goods_count_from_other=goods_count :goods_id=goods_id></COUNTER>
      </div>
    </div>
  </div>
</template>

<script>
import COUNTER from '@/components/COUNTER.vue'

export default {
  components: {
    COUNTER,
  },
  props:{
    goods_state_from_other:{
      type:Boolean,
      default:true
    },
    goods_img:{
      type:String,
      default:'@/assets/logo.png'
    },
    goods_name:{
      type:String,
      required:true
    },
    goods_price:{
      type:Number,
      required:true
    },
    goods_count:{
      type:Number,
      default:1
    },
    goods_id:{
      type:Number,
      required:true
    }
  },
  data() {
    return {
      goods_state:this.goods_state_from_other
    }
  },
  watch:{
    goods_state() {
      this.send_father_state()
    },
    goods_state_from_other() {
      this.goods_state = this.goods_state_from_other
    }
  },
  methods:{
    send_father_state() {
      this.$emit('get_son_state',{goods_id:this.goods_id,goods_state:this.goods_state})
    },
  }
}
</script>

<style lang="less" scoped>
.goods-container {
  + .goods-container {
    border-top: 1px solid #efefef;
  }
  padding: 10px;
  display: flex;
  .thumb {
    display: flex;
    align-items: center;
    img {
      width: 100px;
      height: 100px;
      margin: 0 10px;
    }
  }

  .goods-info {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    flex: 1;
    .goods-title {
      font-weight: bold;
      font-size: 12px;
    }
    .goods-info-bottom {
      display: flex;
      justify-content: space-between;
      .goods-price {
        font-weight: bold;
        color: red;
        font-size: 13px;
      }
    }
  }
}
</style>

7  FOOTER.vue

<template>
  <div class="footer-container">
    <!-- 左侧的全选 -->
    <div class="custom-control custom-checkbox">
      <!-- <input type="checkbox" class="custom-control-input" id="cbFull" v-model=all_checked /> -->
      <input type="checkbox" class="custom-control-input" id="cbFull" @click=all_check :checked="all_checked"/>
      <!-- v-model=all_checked -->
      <label class="custom-control-label" for="cbFull">全选</label>
    </div>

    <!-- 中间的合计 -->
    <div>
      <span>合计:</span>
      <span class="total-price">¥{{ total_price.toFixed(2) }}</span>
    </div>

    <!-- 结算按钮 -->
    <button type="button" class="btn btn-primary btn-settle">结算({{ goods_total_num }})</button>
  </div>
</template>

<script>
export default {
  props:{
    all_checked_from_other:{
      type:Boolean,
      required:true
    },
    total_price:{
      type:Number,
      required:true
    },
    goods_total_num:{
      type:Number,
      required:true
    }
  },
  data() {
    return {
      all_checked:this.all_checked_from_other
    }
  },
  methods:{
    all_check() {
      if (this.all_checked == true) {
        this.all_checked = false
      }
      else {
        this.all_checked = true
      }
      this.$emit('all_check',this.all_checked)
    }
  },
  watch:{
    // all_checked() {
    //   this.all_check()
    // },
    all_checked_from_other() {
      this.all_checked = this.all_checked_from_other
    }
  }
}
</script>

<style lang="less" scoped>
.footer-container {
  font-size: 12px;
  height: 50px;
  width: 95%;
  border-top: 1px solid #efefef;
  position: fixed;
  bottom: 0;
  background-color: #fff;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 10px;
}

.custom-checkbox {
  display: flex;
  align-items: center;
}

#cbFull {
  margin-right: 5px;
}

.btn-settle {
  height: 80%;
  min-width: 110px;
  border-radius: 25px;
  font-size: 12px;
}

.total-price {
  font-weight: bold;
  font-size: 14px;
  color: red;
}
</style>

全选的时候不要使用v-model,当你全选的时候,取消其中一个就会取消全选按钮,取消全选按钮就会取消所有按钮

所以在对于全选按钮,我们不使用 数据驱动视图,仅使用 视图驱动数据,令其仅在点击的时候产生变化

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

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

相关文章

idea中的debug操作详解

行断点 默认模式 方法断点 菱形&#xff0c;加在方法前&#xff0c;用的比较多的地方&#xff1a;加在接口前会进入这个接口的实现类。 异常断点 如果说你的程序抛了某个异常&#xff0c;你需要知道在哪里抛出的&#xff0c;可以直接设置异常断点&#xff0c;设置后程序会…

Shell脚本之循环语句(for、while、until)

目录 一、echo命令二 for循环语句三 while循环语句结构(迭代&#xff09;四. until 循环语句结构五.continue和break和exit 一、echo命令 ?echo -n 表示不换行输出 echo -e 输出转义字符&#xff0c;将转义后的内容输出到屏幕上 常见转义字符&#xff1a; 二 for循环语句 用法…

Baumer工业相机堡盟工业相机如何通过BGAPI SDK设置自动亮度调整BrightnessAuto(自动曝光自动增益)(C++)

自动亮度调整项目场景 Baumer工业相机堡盟相机是一种高性能、高质量的工业相机&#xff0c;可用于各种应用场景&#xff0c;如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能&#xff0c;可以实时传输高分辨率图像。此外&#xff0…

北斗哨兵北斗短报文远程监控系统解决方案

一、项目背景 随着社会发展各行各业都会遇到各种各样的安全问题&#xff0c;监控系统作为安防的第一线安防设备也已广泛部署&#xff0c;然而地处偏僻的监控区域往往面临着难以提供电力供应以及网络供应的问题&#xff0c;类似于山区环境监测&#xff0c;工地监测等复杂的环境布…

Web自动化测试流程:从入门到精通,帮你成为测试专家

B站首推&#xff01;2023最详细自动化测试合集&#xff0c;小白皆可掌握&#xff0c;让测试变得简单、快捷、可靠https://www.bilibili.com/video/BV1ua4y1V7Db 目录 摘要&#xff1a; 步骤一&#xff1a;选取测试工具 步骤二&#xff1a;编写测试用例 步骤三&#xff1a;编…

5月4号软件资讯更新合集.....

&#x1f680; Layui 2.8.2 发布 更新日志 table 修复 autoSort: true 时&#xff0c;更改 table.cache 未同步到 data 属性的问题 修复 多级表头存在 hide 表头属性时&#xff0c;执行完整重载可能出现的错位问题 修复 未开启 page 属性时底边框缺失问题 优化 打印内容中…

大型游戏剧本杀小程序app

大型游戏剧本杀小程序的发展趋势主要表现为以下几个方面&#xff1a; 社交互动&#xff1a;未来大型游戏剧本杀小程序将会更加注重社交互动&#xff0c;为用户提供更多的沟通方式和社交场景&#xff0c;以增强玩家间的互动和参与感。 智能化和AR/VR技术应用&#xff1a…

网络基础项目——全网互通实验

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 前言 本章将会讲解网络基础项目——全网互通实验。 一.实验项目图 二.实验要求 1.全网互通,所有PC机能访问服务器(ping)2.路由器…

DA-Net:用于视网膜血管分割的双分支Transformer和自适应条带上采样

文章目录 DA-Net: Dual Branch Transformer and Adaptive Strip Upsampling for Retinal Vessels Segmentation摘要本文方法整体框架Transformer LayerAdaptive Strip Upsampling Block 实验结果消融实验 DA-Net: Dual Branch Transformer and Adaptive Strip Upsampling for R…

【Python习题集6】类与对象

类与对象 一、实验内容二、实验总结 一、实验内容 1.设计一个Circle类来表示圆&#xff0c;这个类包含圆的半径以及求面积和周长的函数。在使用这个类创建半径为1~10的圆&#xff0c;并计算出相应的面积和周长。 半径为1的圆&#xff0c;面积: 3.14 周长: 6.28 半径为2的圆&am…

【虹科案例】虹科任意波形发生器板卡在声场模拟实验中的应用

声场模拟实验介绍 声场模拟实验是一种通过模拟不同环境下的声场特征来模拟真实世界中声音传输情况的实验方法。通过模拟不同环境下的声场特征&#xff0c;如空间分布、强度、频率等&#xff0c;来模拟真实世界中的声音传输情况&#xff0c;从而对声学相关问题进行研究。 在声…

Java集合框架知识总结

前言 Java集合框架主要由两个接口及其下面的实现类构成&#xff0c;这两个接口分别是Map接口和Collection接口&#xff0c;下面先通过其对应的UML类图看下这两个接口的具体实现&#xff0c;如下 1、Map接口 Map接口的主要实现有我们熟悉的HashMap、HashTable以及TreeMap、Con…

信息技术发展

OSI网络标准协议 物理层&#xff1a;联网的媒介 RS232 FDDI 数据链路层: 网络层接收到的数据分割成可被物理层传输的帧 IEEE802.3/.2 ATM 网络层&#xff1a;网络地址翻译成对应的物理地址&#xff0c;路由 IP ICMP IGMP IPX ARP 传输层&#xff1a;端到端的错误恢复和流量控制…

轻松提升投标技术分?smardaten高性价比原型服务受热捧

日前&#xff0c;某个交通领域的软件公司A遇到了难题&#xff0c;十多个在跟的项目需要在一个月内完成投标准备工作。 应用软件“强甲方需求”的大环境下&#xff0c;A公司又陷“投标高峰期”。 更具挑战性的是&#xff0c;其中&#xff0c;有5个项目要求应标企业提供真实系统的…

一文介绍Linux EAS

能量感知调度&#xff08;Energy Aware Scheduling&#xff0c;简称EAS&#xff09;是目前Android手机中Linux线程调度器的基础功能&#xff0c;它使调度器能预测其决策对CPU能耗的影响。依靠CPU的能量模型&#xff08;Energy Model&#xff0c;简称EM&#xff09;&#xff0c;…

steam搬砖,适合个人操作的创业项目

这个项目主就是在Steam平台买进CSGO道具&#xff0c;再放到网易buff平台卖出。因为进价低出价高&#xff0c;所以每卖出一件道具&#xff0c;利润都相当可观。 关键这玩意背靠Steam这个超大平台&#xff0c;日活几千万&#xff0c;几乎覆盖了市面上的所有热门游戏&#xff0c;…

动态规划——逆序对

逆序对Time Limit: 1000 MSMemory Limit: 5000 KB Description 给定一个长度为N的int型数组a[0,1,2,...N-1], 请计算逆序对个数.当i<j且a[i]>a[j], 则称a[i]与a[j]是一对逆序对.Input 第一行输入M表示包含M组测试数据&#xff0c;每组先输入N (N<50000), 接着输入N…

ios app真机测试到上架App Store详细教程-必看

​转载&#xff1a;https://blog.csdn.net/p312011150/article/details/89374401 ios app真机测试到上架App Store详细教程-必看 Appuploader常见问题 转存失败 重新上传 取消 上架基本需求资料 1、苹果开发者账号&#xff08;如还没账号先申请-苹果开发者账号申请教程&…

​​​​魔兽服务端自定义创建传送门教程

魔兽服务端自定义创建传送门教程 大家好我是艾西,今天跟大家分享下魔兽自定义传送门怎么创建。玩过魔兽的朋友都知道,魔兽这游戏内容多地图也非常大,一个老魔兽玩家很熟悉跑副本的情况下从这个地图到下一个地图都得跑半个小时,更何况对于很多得新手小伙伴了,所有顾及到大…

CUDA编程之矩阵乘法

文章目录 一、矩阵乘法回顾二、CUDA内存架构CUDA中的共享内存CUDA中的共享内存使用方法静态申请内存动态申请内存 三、分解矩阵乘法 / 平铺矩阵乘法四、实战代码DS_M 和 DS_N的索引方式解释 一、矩阵乘法回顾 CPU版本&#xff1a; GPU版本&#xff1a; 核函数如下&#xff1…