资讯专栏INFORMATION COLUMN

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

helloworldcoding / 2046人阅读

摘要:在做微信小程序时,觉得小组里对购物车的实现不是很完美,就自己尝试的写了下,然后用到了父子组件传值,父子组件传值的话,和框架上是非常相似的,以及这个函数,有个注意点,自己不怎么用,一时间有差点忘了,这里记录下效果图子组件实现要实现图中删除的效

在做微信小程序时,觉得小组里对购物车的实现不是很完美,就自己尝试的写了下,然后用到了父子组件传值,父子组件传值的话,和vue框架上是非常相似的,以及calc这个css函数,calc有个注意点,自己不怎么用,一时间有差点忘了,这里记录下
1.效果图
2.子组件实现

要实现图中删除的效果,使用组件的形式更好做点,我当时本想直接在pages里实现,不过结果就是,滑动时,所有的商品都显示了删除按钮,除非用数组将每个商品要移动的距离存储起来,不过这样的话就很麻烦,所以我也是用组件来实现的

关于微信组件,可以直接点击链接访问官网查看自定义组件

子组件index.wxml


  
    
    
  
  
    
                
    
    
      {{commodity.title}}
      规格:{{commodity.standard?commodity.standard:"无"}}
      
        ¥{{commodity.price}}
        
          
        
      
    
  
  
    
    删除
  

子组件index.wxss

/* 商品 */
.commodityItem{
  display: flex;
  position: relative;
  padding: 10rpx 24rpx 20rpx 30rpx;
  box-sizing: border-box;
  background: #fff;
  transition: all .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,这里用的是假数据,所以操作上会有一些是联调时不必要的操作


  
    
      
      {{items.shopname}}
    
    满¥100包邮,满10件包邮
    
      
    
  
    
        
            
        
            全选
        
        
      合计:
      ¥{{countPrice}}
    
        
    

父组件index.wxss

page{
  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.js

Page({

  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*/

在子组件中调用

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.部分想法

其实在样式上还是挺快就完成了,就是在计算商品价格的时候,想了挺久

在计算价格时,当时就有点蒙圈,总是想着要怎么判断他是增加数量还是减少数量,然后就陷入死循环的之中。

其实不用想她是增加还是减少数量,因为你都是传的是商品的数量,而且在计算时,也是判断了商品是否选中,所以,直接点,计算价格乘以数量就可以了

然后选中的商品数量的统计就和计算价格的思路是一样的了

正在努力学习中,若对你的学习有帮助,留下你的印记呗(点个赞咯^_^)

往期好文推荐:

判断iOS和Android及PC端

css实现波浪线及立方体

微信小程序中遇到的多规格问题(一)

实现单行及多行文字省略号

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99216.html

相关文章

  • 信小程序scroll-viewflex布局问题

    摘要:关于微信小程序的组件,第一次写的时候是直接在中用了一层容器包裹子元素,然后用了布局,并且是用了组件来实现的横向滚动,后面有提出改进,但是不记录下,就发现过了几天,就有点懵了效果图在里加一层容器,使用布局实现这里用布局实现的话,就要用组 关于微信小程序的scroll-view组件,第一次写的时候是直接在scroll-view中用了一层容器包裹子元素,然后用了flex布局,并且是用了组件来...

    nihao 评论0 收藏0
  • 信小程序店铺评分组件及vue中用svg实现评分显示组件

    摘要:在微信小程序中,有遇到要展示店铺评分,或者是订单完成后对商品进行评价,用到了星星展示,查了下,在微信中无法使用实现图片,微信中只能将图片转成来显示,所以是在中使用的来实现评分效果图微信中的可以点击及显示,但是,显示的话,在分,点多分的时候, 在微信小程序中,有遇到要展示店铺评分,或者是订单完成后对商品进行评价,用到了星星展示,查了下,在微信中无法使用svg实现图片,微信中只能将svg图...

    BetaRabbit 评论0 收藏0
  • 记一次信小程序在安卓白屏问题

    摘要:在做小程序的时候,做到了一个限时商品售卖,用到了倒计时,因为这个原因导致了安卓手机上使用小程序时,将小程序放入后台运行一段时间后,再次进入小程序后出现了页面白屏或者点击事件失效的情况,这里记录下相关代码文件我这里是使用了自定义组件的形式来渲 在做小程序的时候,做到了一个限时商品售卖,用到了倒计时,因为这个原因导致了安卓手机上使用小程序时,将小程序放入后台运行一段时间后,再次进入小程序后...

    Hydrogen 评论0 收藏0
  • 去除富文本中html标签及vue、react、信小程序过滤器

    摘要:在获取富文本后,又只要显示部分内容,需要去除富文本标签,然后再截取其中一部分内容然后就是过滤器,在微信小程序中使用还是挺多次的,在及中也遇到过富文本去除标签去除标签及空格的丰富及饿哦塞尔去除富文本中的标签限定符都是贪婪的,因为它们会尽可能 在获取富文本后,又只要显示部分内容,需要去除富文本标签,然后再截取其中一部分内容;然后就是过滤器,在微信小程序中使用还是挺多次的,在vue及reac...

    tulayang 评论0 收藏0
  • Vue2.0生命周期及路由导航守卫

    摘要:的生命周期,有的时候还是会不熟悉的样子,找了点相关的文章,然后自己尝试着做了点示例,这里记录下,说不定面试就用上了生命周期的相关图片生命周期及路由的钩子函数实例初始化之后,初始化注入及响应前被调用实例已经创建完成之后被调用,属性已绑定,但还 Vue的生命周期,有的时候还是会不熟悉的样子,找了点相关的文章,然后自己尝试着做了点示例,这里记录下,说不定面试就用上了 1.Vue生命周期的相关...

    chengjianhua 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<