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

Vue 跨组件传参 (1.事件总线eventBus,2.vuex)实现购物车

案例实现购物车, 跨组件传参。这里用的是事件总线eventBus .。
动态组件。
点击购买按钮后,购物车数量统计自动++
,相同产品自加1,没有的商品添加到购物车。
点击购物车时,能看到加入的商品数据。
刷新页面数据不会丢失。
(计算属性要有return 返回值得。)
在这里插入图片描述
在这里插入图片描述

代码如下

<style>
  html,
  body,
  ul,
  li {
    margin: 0;
    padding: 0;
  }
  ul li {
    list-style: none;
  }
  .product {
    display: flex;
    justify-content: center;
    align-items: center;
    border-bottom: solid 0.01rem fuchsia;
    padding: 0.5rem 1.5rem;
    flex-direction: column;
  }
  .product img {
    width: 75%;
  }
  .product h5 {
    color: deeppink;
  }
  html,
  body,
  #app {
    height: 100%;
  }
  #app {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .list {
    flex: 1;
    height: 100%;
    overflow: auto;
  }
  .nav {
    height: 60px;
  }
  .nav ul {
    display: flex;
    justify-content: space-around;
  }
  .nav .active {
    color: deeppink;
  }
  .nav ul li {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    position: relative;
  }
  .nav ul li img {
    width: 26px;
    margin: 0.5rem;
  }
  .nav ul li span {
    font-size: 0.8rem;
  }
  .dot {
    position: absolute;
    z-index: 10;
    width: 20px;
    height: 20px;
    padding: 0.2rem;
    border-radius: 50%;
    background-color: rgba(200, 0, 0, 0.7);
    color: white;
    text-align: center;
    top: -6px;
    left: 20px;
  }
  .btn {
    border: none;
    background-color: orangered;
    text-align: center;
    color: white;
    width: 5rem;
    height: 1.5rem;
  }
  .title {
    padding: 0;
    margin: 0.5rem 1rem;
  }
  .sum-price {
    position: fixed;
    background-color: #4bd67c;
    bottom: 70px;
    right: 5px;
    padding: 0.5rem 1rem;
    color: white;
  }
</style>


<div id="app">
  <!-- 动态组件,通过设置is属性绑定当前显示的组件内容 -->
  <component style="height: 100%;" :is="currentComponent"></component>

  <div class="nav">
    <ul>
      <li @click="setPage('list', 0)" :class="{active: selectIndex == 0}">
        <img
          :src="selectIndex==0? './assets/images/list-sel.png': './assets/images/list.png'"
        />
        <span>商品列表</span>
      </li>
      <li @click="setPage('cart', 1)" :class="{active: selectIndex == 1}">
        <img
          :src="selectIndex==1? './assets/images/cart-sel.png': './assets/images/cart.png'"
        />
        <span>购物车</span>
        <span class="dot">{{cartCount}}</span>
      </li>
    </ul>
  </div>
</div>
<!-- 就会找一个离我们最近的服务器进行访问,加快访问速度 -->
<!-- cdn服务器部署和开发人员没有关系,是运维的环节 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@2.1.1/dist/jquery.min.js"></script>
<script>
  // 非相关组件之间传参 使用事件总线
  //  所谓事件总线是一种开发思想,所有的事件派发和监听都是同一个空白实例中进行
  var eventBus = new Vue();
  // 我们在vue对象的prototype属性上定义一个变量
  //  此属性在vue实例中能被访问到
  Vue.prototype.$eventBus = eventBus;
  // 首页
  var list = {
    template: `<ul class="list">
        <li class="product" v-for="item in products" :key="item.skuId">
          <img :src="item.image" :alt="item.name" />
          <h5>{{item.name}}</h5>
          <button class="btn" @click="buy(item)">购买</button>
        </li>
      </ul>`,
    data() {
      return { products: [] }; //
    },
    created() {
      $.getJSON(
        "https://o2api.jd.com/data?body=%7B%22query%22%3A%22query%20getCommodities(%24ids%3A%20String)%7Bcommodities(ids%3A%20%24ids)%7BgroupId%2C%20groupName%2C%20productList%7BcanSell%20skuId%20name%20image%20commentCount%20goodRate%20jdPrice%20pcpPrice%20plusPrice%20tag%20copyWriting%20copyWritingDown%20backUpWords%7D%7D%7D%22%2C%22operationName%22%3A%22getCommodities%22%2C%22variables%22%3A%7B%22ids%22%3A%22%5B03504985%2C03505081%5D%22%7D%2C%22config%22%3A%7B%22cache%22%3Afalse%2C%22trim%22%3Atrue%2C%22map%22%3A%7B%22keyBy%22%3A%22groupId%22%2C%22valueField%22%3A%22productList%22%7D%7D%7D&_=1568689310891"
      ).then((res) => {
        this.products = res.data["03504985"];
      });
    },
    methods: {
      buy(product) {
        // 事件派发, 参数一叫事件名字,参数二是传递的参数
        this.$eventBus.$emit("buyClick", product);
      },
    },
  };

  // 购物车页面
  var cart = {
    template: `
    <div class="list">
      <h1 class="title">购物车</h1>
      <ul>
        <li class="product" v-for="item in products" :key="item.skuId">
          <img :src="item.image" :alt="item.name" />
          <h5>{{item.name}}</h5>
          <p>
            <button @click="subj(item)">-</button>
            <input v-model="item.isChecked" type="checkbox"/>
              {{item.jdPrice}}X{{item.amount}}
            <button @click="item.amount+=1">+</button>
          </p>
        </li>
      </ul>
      <div class="sum-price">
        <p>总价:¥{{sumPrice}}元</p>
      </div>
    </div>`,
    data() {
      return {
        products: [],
      };
    },
    
    created() {
      // 在购物车页面,当已进入这个页面就从本地取数据
      var strShopCarts = localStorage.getItem("shop-carts");
      if (strShopCarts) {
        this.products = JSON.parse(strShopCarts);
      }
    },
    computed: {
      // 计算属性设置总价
      sumPrice() {
        return this.products
          .filter((item) => item.isChecked) // 过滤
          .reduce((pre, cur) => pre + cur.jdPrice * cur.amount, 0); // 求和
      },
    },
    methods:{
		subj(item){
			console.log(item, ‘是接受减法时的参数对象’)
			item.amount--
            if(item.amount<1){ // 对象的数量小于1时,数量为0.
              item.amount = 0
            }
		}
	}
  };

  var app = new Vue({
    el: "#app",
    data: {
      selectIndex: 0,
      currentComponent: "list",
      // cartCount: 0,
      shopCarts: [], // 购物车数据
    },
    // 注册组件
    components: {
      list,
      cart,
    },
    methods: {
      // 动态接受页面组件
      setPage(page, index) { 
        // 设置当前选中的组件
        this.currentComponent = page;
        // 设置当前选中的底部索引
        this.selectIndex = index;
      },
    },
    created() {
      // 做事件监听 v代表传递过来的商品信息
      this.$eventBus.$on("buyClick", (v) => {
        // console.log(v);
        // 查找符合条件的数据的下标 findIndex()
        var index = this.shopCarts.findIndex(
          (item) => item.skuId === v.skuId
        );
        if (index > -1) {
          // this.shopCarts 
          // 如果存在这个商品数量就加1 
          this.shopCarts[index].amount += 1;
        } else {  // 如果没有就新加入购物车一个商品数据
          // 使用了对象的扩展运算符
          this.shopCarts.push({ ...v, amount: 1, isChecked: false });
        }

        // 存储到本地 为了点击购物车的时候可以看到加入购物车的数据
        localStorage.setItem("shop-carts", JSON.stringify(this.shopCarts));
        // if(this.shopCarts.findIndex())
        // this.cartCount++;
      });
      var strShopCarts = localStorage.getItem("shop-carts");
      if (strShopCarts) {
        this.shopCarts = JSON.parse(strShopCarts);
      }
    },
    computed: {
      cartCount() {
        // 根据当前的shopCarts数据计算总数量
        return this.shopCarts.reduce((pre, cur) => {
          return pre + cur.amount;
        }, 0);
      },
    },
  });
</script>

相关文章:

  • 阿里云机器学习8月特别推荐
  • [工具]json转类
  • 数据请求一个数组,向数组里push新增内容
  • iOS - MVP 架构模式
  • <component :is=“动态组件“></component>
  • 大数据解决方案如何满足零售行业进销存数据的实时性存储与更新
  • react项目中实现打印预览功能
  • easyUI loyout tabs自适应宽度
  • react封装一个打印功能
  • 在linux环境下编译C++ 程序
  • react项目中,在tab列表上展示某个字段以 数组形式 展示
  • Spark Streaming官方文档学习--下
  • Vue 判断两个时间选择框的校验element 。开始时间不能大于结束时间
  • 为什么不能访问django自带的索引页
  • SSIS 数据类型和类型转换
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Apache的80端口被占用以及访问时报错403
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • Druid 在有赞的实践
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • golang中接口赋值与方法集
  • HTTP那些事
  • Javascript设计模式学习之Observer(观察者)模式
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • React-redux的原理以及使用
  • 关于List、List?、ListObject的区别
  • 设计模式 开闭原则
  • #AngularJS#$sce.trustAsResourceUrl
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • $(function(){})与(function($){....})(jQuery)的区别
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (solr系列:一)使用tomcat部署solr服务
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (论文阅读40-45)图像描述1
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (十)T检验-第一部分
  • (学习日记)2024.02.29:UCOSIII第二节
  • (转)http协议
  • (转)树状数组
  • (转载)深入super,看Python如何解决钻石继承难题
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .net 后台导出excel ,word
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .net程序集学习心得
  • .NET命令行(CLI)常用命令
  • /etc/X11/xorg.conf 文件被误改后进不了图形化界面
  • []Telit UC864E 拨号上网
  • [BUG] Hadoop-3.3.4集群yarn管理页面子队列不显示任务
  • [BUUCTF NewStarCTF 2023 公开赛道] week4 crypto/pwn