宝哥软件园

微信小程序之购物车和父子组件传值及计算的注意事项

编辑:宝哥软件园 来源:互联网 时间:2021-12-04

1.效果图

微信小程序之购物车和父子组件传值及calc的注意事项(图1)

2.子组件实现

要实现图中删除的效果,使用组件的形式更好做点,我当时本想直接在页里实现,不过结果就是,滑动时,所有的商品都显示了删除按钮,除非用数组将每个商品要移动的距离存储起来,不过这样的话就很麻烦,所以我也是用组件来实现的关于微信组件,可以直接点击链接访问官网查看自定义组件子组件index.wxmlview类=' commodity item ' bindtustart=' handleTouchStart ' bindtusmove=' handleTouchMove ' style=' transform : translatex({-right space } } } px)'视图类=' selectedBtn ' bind tap=' handleSelect ' data-is-selected=' { { commodity。被选中} } '视图类=' noSelected ' wx : if=' { { commodity。被选中==0 } } '/查看图像类=' selectedImg ' wx 333336规格:{{commodity.standard?commodity.standard: '无} }/view view class=' count ' view class=' price ' $ { { commodity。price } }/view class=' commodity num ' I-input-number value=' { { selected num } } ' min=' 1 ' max=' { { commodity。stock } } ' bind change=' numChange '/view/view/view class=' deleteBtn ' image class=' deleteImg ' src='/images/delete。png '/image text class=' delete text '删除/文本/视图/视图子组件index.wxss/*商品*/.商品项目{ display : flex相对位置:padd : 10 rpx 24 rpx 20 rpx 30 rpx盒子尺寸:边框盒子;背景# ffftransition: al

l .5s;}/* 选择按钮 */.selectedBtn{ display: flex; align-items: center; width: 80rpx;}.noSelected{ width: 46rpx; height: 46rpx; border-radius: 50%; border: 1px solid #ef5225;}.selectedBtn .selectedImg{ width: 50rpx; height: 50rpx;}/* 商品信息 */.commodityInfo{ display: flex; width: calc(100% - 80rpx);}.commodityImg{ margin-right: 18rpx; width: 220rpx; height: 220rpx;}.commodityImg image{ width: 100%; height: 100%; vertical-align: middle; }/* 商品title */.commodityTitle{ width: calc(100% - 220rpx);}.title{ display: -webkit-box; width: 100%; height: 70rpx; line-height:35rpx; font-size: 24rpx; font-weight:600; overflow: hidden; -webkit-line-clamp: 2; -webkit-box-orient: vertical;}.standard{ padding-top: 16rpx; width: 100%; height: 90rpx; box-sizing: border-box;}.count{ display: flex; align-items: center; justify-content: space-between; width: 100%; height: 60rpx;}/* 删除按钮 */.deleteBtn{ display: flex; position: absolute; width: 70px; height: 100%; top: 0rpx; right: -70px; flex-direction: column; align-items: center; justify-content: center; background: #ef5225;}.deleteImg{ margin-bottom: 10rpx; width: 50rpx; height: 50rpx; vertical-align: middle;}.deleteText{ color: #fff;}子组件index.json,这里用了iview中的数字输入框{ "component": true, "usingComponents": { "i-input-number": "/component/iview/input-number/index" }}
  • 子组件index.js
Component({  properties: {    commodity: Object,  },  data: {    touchStart: null,    rightSpace: 0,    selectedNum: 1,  },  methods: {    /* 商品是否选中 */    handleSelect() {            let selectedNum = this.data.selectedNum;      let commodity = this.data.commodity;      if(commodity.isselected == 0) {        commodity.isselected = 1;      } else {        commodity.isselected = 0;      }            this.triggerEvent('handleselect', { commodity, selectedNum})    },    /* 处理触摸滑动开始 */    handleTouchStart(e) {      /* 记录触摸滑动初始位置 */      let touchStart = e.changedTouches[0].clientX;      this.setData({        touchStart      })    },    /* 处理触摸滑动 */    handleTouchMove(e) {      console.log(e)      let moveSpace = e.changedTouches[0].clientX;      let touchStart = this.data.touchStart;      if (touchStart != null) {        if (moveSpace - touchStart > 70) {          this.setData({            touchStart: null,            rightSpace: 0          })        }        else if (moveSpace - touchStart < -70) {          this.setData({            touchStart: null,            rightSpace: 70          })        }      }    },    numChange(e) {        let selectedNum = e.detail.value;        let commodity = this.data.commodity;        this.setData({            selectedNum        })        this.triggerEvent('handleselect', { commodity, selectedNum})    }  }})

3.父组件实现

  • 父组件index.wxml,这里用的是假数据,所以操作上会有一些是联调时不必要的操作
<view class="cart">  <view class="item" wx:for="{{cartList}}" wx:key="{{items.shopid}}" wx:for-item="items">    <view class="storeInfo">      <image class="avatar" src="{{items.logo}}"></image>      <view class="storeName">{{items.shopname}}</view>    </view>    <view class="discount">满¥100包邮,满10件包邮</view>    <view class="commodity" wx:for="{{items.commodity}}" wx:key="{{item.id}}">      <cart-item commodity="{{item}}" bind:handleselect="handleSelect" />    </view>  </view>    <view class="count">        <view class="selectAll" bindtap="handleSelectAll">            <view class="noSelected" wx:if="{{!isSelectedAll}}"></view>        <image class="selectedImg" wx:else src="/images/selected.png"></image>            <text class="selectAllText">全选</text>        </view>        <view class="countPrice">      <text>合计:</text>      <text>¥{{countPrice}}</text>    </view>        <view class="account">      <text>结算</text>      <text>({{countSelectedNum}})</text>    </view>    </view></view>父组件index.wxsspage{  background: #f8f8f8;}.cart{    padding-bottom: 100rpx;  font-size: 26rpx;}.item{  border-bottom: 1px solid #eee;}/* 头部店铺信息 */.storeInfo{  display: flex;  padding: 18rpx 0rpx 18rpx 30rpx;  background: #fff;  box-sizing: border-box;}.storeInfo .avatar{  width: 56rpx;  height: 56rpx;  border-radius: 50%;  vertical-align: middle;}.storeInfo .storeName{  margin-left: 16rpx;  line-height: 56rpx;}/* 包邮信息 */.discount{  padding-left: 30rpx;  height:50rpx;  line-height: 50rpx;  font-size:20rpx;  color: #666;  box-sizing: border-box;}/* 底部操作 */.count{    display: flex;    position: fixed;    padding-left: 30rpx;    bottom: 0;  left: 0;    width: 100%;    height: 100rpx;    line-height: 100rpx;  box-sizing: border-box;  color: #232323;    background: #eee;}/* 全选 */.selectAll{    display: flex;  padding-right: 20rpx;    align-items: center;    width: 25%;  font-size: 30rpx;}.selectAll .noSelected{  width: 46rpx;  height: 46rpx;  border-radius: 50%;  border: 1px solid #ef5225;}.selectAll .selectedImg{  width: 50rpx;  height: 50rpx;}.selectAllText{    margin-left: 18rpx;}.countPrice{    position: absolute;  top: 0;  right: 270rpx;  height: 100%;  line-height: 100rpx;  text-align: center;  font-size: 30rpx;}.countPrice text{  margin-right: 15rpx;}.account{  position: absolute;  top: 0;  right: 0;    width: 270rpx;  height: 100%;  line-height: 100rpx;  text-align: center;  font-size: 30rpx;  background: #ef5225;  color: #fff;}
  • 父组件index.json,引用子组件
{  "usingComponents": {    "cart-item": "/component/cart/index"  }}父组件index.jsPage({  data: {    cartList: [      {        shopname: '猫咪小店',        logo: '/images/avatar.jpeg',        shopid: 11,        commodity: [          {            id: 1,            image:'/images/commodity.jpg',            title: '雅诗兰黛鲜活焕亮红石榴晚霜50ml 补水保湿 滋润排浊',            standard: '111 + 黑色',            price: '100',            stock: 10,            quantity: 1,            isselected: 0,          },           {            id: 2,            image:'/images/avatar7.jpg',            title: '雅诗兰黛鲜活焕亮红石榴晚霜50ml 补水保湿 滋润排浊',            price: '10',            stock: 5,            quantity: 1,            isselected: 0,          }        ]      },      {        shopname: '猫咪小店',        logo: '/images/avatar5.jpg',        shopid: 450,        commodity: [          {            id: 3,            image:'/images/commodity.jpg',            title: '雅诗兰黛鲜活焕亮红石榴晚霜50ml 补水保湿 滋润排浊',            price: '90',            stock: 10,            quantity: 1,            isselected: 0,          },          {            id: 4,            image:'/images/avatar7.jpg',            title: '雅诗兰黛鲜活焕亮红石榴晚霜50ml 补水保湿 滋润排浊',            price: '100',            stock: 5,            quantity: 1,            isselected: 0,          },           {            id: 5,            image:'/images/commodity.jpg',            title: '雅诗兰黛鲜活焕亮红石榴晚霜50ml 补水保湿 滋润排浊',            standard: '111 + 黑色',            price: '100',            stock: 2,            quantity: 1,            isselected: 0,          }        ]      },      {        shopname: '猫咪小店',        logo: '/images/avatar.jpeg',        shopid: 550,        commodity: [          {            id: 6,            image:'/images/avatar8.jpg',            title: '雅诗兰黛鲜活焕亮红石榴晚霜50ml 补水保湿 滋润排浊',            standard: '111 + 黑色',            price: '100',            stock: 1,            quantity: 1,            isselected: 0,          }        ]      },    ],        /* 商品是否全选中 */        isSelectedAll: false,        /* 已选中商品的价格 */        countPrice: 0,    /* 统计所有选中的商品数量 */    countSelectedNum: 0,  },  /* 处理商品选中 */  handleSelect(e) {        let countPrice = 0;    let countSelectedNum = 0;    let cartList = this.data.cartList;    let length = cartList.length;        /* 因为是假数据,所以需要循环查找到对应的数据将其替换 */    for(let i = 0; i < length; i++) {      for(let j = 0; j < cartList[i].commodity.length; j++) {                if (cartList[i].commodity[j].id == e.detail.commodity.id) {          cartList[i].commodity[j] = e.detail.commodity;          cartList[i].commodity[j].selectedNum = e.detail.selectedNum;        }        if (cartList[i].commodity[j].isselected == 1) {          /* 点击选中的时候,计算价格,要判断下设置的商品选中数量,           * 我这里的是对点击了的商品才设置了选中的数量,所以需要对没有点击的商品数量设置为1,然后就默认的加一           */          if (cartList[i].commodity[j].selectedNum != undefined) {            countPrice += cartList[i].commodity[j].price * cartList[i].commodity[j].selectedNum;            countSelectedNum += cartList[i].commodity[j].selectedNum          } else {            countPrice += cartList[i].commodity[j].price * 1;            countSelectedNum += 1;          }        }      }    }        /* 对是否全选中进行判断 */        let isSelectedAll = true;        for (let i = 0; i < length; i++) {            for (let j = 0; j < cartList[i].commodity.length; j++) {                /* 若商品中的isselecetd有为0的就终止循环,直接设置为未全选 */                if (cartList[i].commodity[j].isselected == 0) {                    isSelectedAll = false;                    break;                }            }        }    this.setData({      cartList,            isSelectedAll,            countPrice,      countSelectedNum    })  },    /* 全选中商品 */    handleSelectAll() {        let isSelectedAll = !this.data.isSelectedAll;        let cartList = this.data.cartList;        let length = cartList.length;    let countPrice = 0;    let countSelectedNum = 0;        /* 遍历数据中的isselected来进行全选的操作 */        for(let i = 0; i < length; i++) {            for (let j = 0; j < cartList[i].commodity.length; j++) {                if(isSelectedAll) {                    cartList[i].commodity[j].isselected = 1;          /* 全选的时候,计算价格,要判断下设置的商品选中数量,           * 我这里的是对点击了的商品才设置了选中的数量,所以需要对没有点击的商品数量设置为1,然后就默认加一           */          if (cartList[i].commodity[j].selectedNum != undefined) {            countPrice += parseInt(cartList[i].commodity[j].price) * cartList[i].commodity[j].selectedNum;            countSelectedNum += cartList[i].commodity[j].selectedNum;          } else {            countPrice += cartList[i].commodity[j].price * 1;                countSelectedNum += 1;                  }                } else {                    cartList[i].commodity[j].isselected = 0;                }            }        }        this.setData({            isSelectedAll,            cartList,      countPrice,      countSelectedNum        })    },})

4.父子组件传值

  • 较常用的都是父组件往子组件传值,所以子组件往父组件传值就会不是很熟悉
  • 我这里的话,是因为用的假数据,在点击商品选中或者不选中时,需要改变商品里的选中属性,所以用到了子组件往父组件传值,也包括传递选中的商品数量
  • 子组件往父组件传值的话,是通过在调用this.triggerEvent()来实现的
/* 在父组件中定义方法:bind:handleselect或者也可以直接写成bindhandleselect*/<cart-item commodity="{{item}}" bind:handleselect="handleSelect" />在子组件中调用this.triggerEvent('handleselect', { commodity, selectedNum})这个this.triggerEvent('handleselect', { commodity, selectedNum })方法中,handleselect的名称要与父组件中引用子组件时绑定的方法名称一样,后面的对象就是传递的值,也可以直接是以直接量的形式传递,然后再父组件中通过e.detail来获取对应的值handleSelect(e) {    console.log(e.detail)    console.log(e.detail.commodity)    console.log(e.detail.selectedNum)}

5.calc的注意事项

  • 我以前也遇到过,然后现在再用的时候,一时间把这点给忘了,在看到编译器样式的时候,才猛然想起
.user-content{    padding: 10px 0 10px 50px;    width: calc(100% - 50px);  /* 计算宽度,'+'或'-'符号前后有空格 */    height: 18px;}
  • css中使用calc可以进行简单的运算:
  • 单位可以是百分比,px,rem,em等单位
  • 使用"+","-","*","/"运算符(使用"+"或者"-"符号时,符号前后必须加上空格)
  • 在Firefox浏览器上使用要加上-moz前缀
  • chrome浏览器上使用要加上-webkit前缀
  • (使用"+"或者"-"符号时,符号前后必须加上空格)

6.部分想法

  • 其实在样式上还是挺快就完成了,就是在计算商品价格的时候,想了挺久
  • 在计算价格时,当时就有点蒙圈,总是想着要怎么判断他是增加数量还是减少数量,然后就陷入死循环的之中。
  • 其实不用想她是增加还是减少数量,因为你都是传的是商品的数量,而且在计算时,也是判断了商品是否选中,所以,直接点,计算价格乘以数量就可以了
  • 然后选中的商品数量的统计就和计算价格的思路是一样的了
正在努力学习中,若对你的学习有帮助,留下你的印记呗(点个赞咯^_^)
更多资讯
游戏推荐
更多+