11、微信小程序——购物车

目录

1、代码分析

1.1  dom结构分析

1.2  全选控制反选

1.3  反选控制全选

1.4、计算总价

1.4 加、减

2、效果、代码演示 

1、代码分析

1.1  dom结构分析

购物车的组件结构主要由两部分组成:多选框部分( checkbox-group ) + 全选框部分( view )

1.2  全选控制反选

业务逻辑:

1、全选框(选中)——》 多选框(选中)、全选框(不选中)——》 多选框(不选中)

2、令复选框跟随全选框的状态变化——遍历数据,设置每条数据的 isChecked 状态

注意:因为无法直接操作数据,所以需要先行拷贝数据,再对其进行遍历(在本项目中,所有需要对数据进行遍历、筛选操作的步骤,都需要先拷贝数据)

 allChecked(e){
        console.log(e);  //触发点击事件,拿到全选框的事件源对象
        // 全选框: 状态为 true时,令其为 false,当状态为 false时,令其状态变为 true
        if(this.data.isAllChecked){
        // 遍历数据,令复选框的状态跟随全选框变化
        // 拷贝数据、遍历数据
        let goodslist=JSON.parse(JSON.stringify(this.data.goods))
        goodslist.forEach(item=>item.isChecked=false)
            this.setData({
                isAllChecked:false,
                goods:goodslist  //重新渲染
            })
        }else{
            let goodslist=JSON.parse(JSON.stringify(this.data.goods))
            goodslist.forEach(item=>item.isChecked=true)
            this.setData({
                isAllChecked:true,
                goods:goodslist
            })
        }
    },

1.3  反选控制全选

业务逻辑:

1、多选框(全部选中)——》全选框(选中)

因为复选框有多个,全选框只有一个,所以多选框控制全选框被选中的前提是确定每一个多选框都被选中了  ,打印复选框的事件源对象,发现复选框有一 detail.value 属性,可显示 复选框为 true 的对象 / 数量。所以当 e.detail.value.length===this.data.goods.length 时,表示复选框都被选中了

 2、多选框(有一不选中)——》全选框(不选中)

遍历数据( forEach ) 并 检查元素 ( includes ),如果 e.detail.value 中包含 数据id,则令该复选框的 isChecked=true,否则为 false

 // 单选控制全选
    changeCound(e) {
        console.log(e);
        let checkedArr = e.detail.value
        if (checkedArr.length == this.data.goods.length) {
            let goodsList = JSON.parse(JSON.stringify(this.data.goods))
            goodsList.forEach(item => item.isChecked = true)
            this.setData({
                isAllChecked: true,
                goods: goodsList
            })
        } else {
            let goodsList = JSON.parse(JSON.stringify(this.data.goods))
            goodsList.forEach(item => {
                if (checkedArr.includes(item.id)) {
                    item.isChecked = true
                } else {
                    item.isChecked = false
                }
            })
            this.setData({
                isAllChecked: false,
                goods: goodsList
            })
        }
    },

1.4、计算总价

通常用 reduce 来计算总价,其中 total 表示旧值,item表示新值,0为初始值

. reduce( ( total , item ) => { } , 0 )

 // 计算总价
    computedTotalPrice() {
        let totalPrice = this.data.goods.reduce((total, item) => {
            if (item.isChecked) {
                return total + item.num * item.price
            } else {
                return total
            }
        }, 0)
        this.setData({
            totalPrice: totalPrice
        })
    },

1.4 加、减

 // 加、减、删除
    handle: function (e) {
        let id = e.currentTarget.dataset.id
        console.log(id);
        var index = e.currentTarget.dataset.index
        var val = `goods[${index}].num`  //对数据对象 goods 中的 num 属性进行修改
        let oldnum = this.data.goods.find(item => item.id == id).num //查找
        console.log(oldnum);
        // 减
        if (e.currentTarget.dataset.name == "mulse") {
            let newNum = oldnum - 1
            if (newNum > 0) {
                this.setData({
                    [val]: newNum
                })
            }else if(newNum == 0){
                let goodsList = JSON.parse(JSON.stringify(this.data.goods))
                let newGoodList=goodsList.filter(item=>item.id!==id)
                this.setData({
                    goods:newGoodList
                })
            }
            // 加
        }else if(e.currentTarget.dataset.name=="add"){
            let newnum=++oldnum
            this.setData({
                [val]:newnum
            })
        }  
          // 删除
         else if (e.currentTarget.dataset.name == "del") {
              let goodslist = JSON.parse(JSON.stringify(this.data.lists))
              let newLists = goodslist.filter(item => item.id !== id)
              this.setData({
                  lists: newLists
              })
          }
        this.computedTotalPrice()
    }
})

2、代码演示 

 index.wxml:

<checkbox-group bindchange="changeCound" class="top">
    <view wx:for="{{goods}}" wx:key="id" class="checkbox">
        <view class="chleft">
            <checkbox value="{{item.id}}" checked="{{item.isChecked}}" class="cleft"></checkbox>
            <image src="{{item.imgUrl}}" mode="" class="pic" />
        </view>
        <view class="Box">
            <view class="box-left">
                <text class="name">{{item.name}}</text>
                <text class="price">¥{{item.price}}</text>
            </view>
            <view class="box-right">
                <text bindtap="handle" data-id="{{item.id}}" data-name="mulse" data-index="{{index}}">-</text>
                <text>{{item.num}}</text>
                <text bindtap="handle" data-id="{{item.id}}" data-name="add" data-index="{{index}}">+</text>
                <text bindtap="handle" class="del">x</text>
            </view>
        </view>
    </view>
</checkbox-group>
<view class="bottom">
    <view class="bottom-box" bindtap="allChecked">
        <label>
            <checkbox value="" checked="{{isAllChecked}}" />
            <text>全选</text>
        </label>
    </view>
    <view class="total">
        {{totalPrice}} 元
    </view>
</view>

index.scss

.top {
    height:90vh;
    overflow: auto;
    .checkbox {
        position: relative;
        width: 100vw;
        height: 100px;
        border: 1px solid #eee;
        display: flex;
        flex-direction: row;
        .chleft{
            display: flex;
            flex-direction: row;
            align-content: center;
            width: 41%;
            .cleft {
                margin-left: 10px;
                margin-right: 10px;
                line-height: 100px;
            }
            .pic {
                width:80px;
                height: 80px;
                margin-top: 10px;
                object-fit: cover;
            }
        }
        .Box{
            width: 59%;
            height: 100%;
            background-color: #fff;
            .box-left{
                position: relative;
                width: 100%;
                height: 50%;
                text{
                    position: relative;
                    width:50px;
                    height: 20px;
                    margin-left: 10px;
                }
                .name{
                    position: absolute;
                    top:20rpx;
                    left:5rpx;
                }
                .price{
                    position: absolute;
                    top:20rpx;
                    right:5rpx;
                    text-align: left;
                }
            }
            .box-right{
                position: relative;
                margin-top: 17px;
                >text{
                    width: 20px;
                    margin-left: 10px;
                    font-weight: bolder;
                }
                .del{
                    position: absolute;
                    top:-2px;
                    right: 10px;
                    margin-left: 100px;
                }
            }
        }
    }
}
.bottom{
    position: fixed;
    bottom: 0;
    left:0;
    width: 100%;
    height: 11vh;
    box-shadow: 5px 5px 5px 5px rgb(204, 204, 204);
    line-height: 11vh;
    display: flex;
    flex-direction: row;
    .bottom-box{
        width: 50%;
        margin-left: 10px;
    }
    .total{
        width: 50%;
        text-align: right;
        padding-right: 15px;
    }
}

index.js

Page({
    data: {
        goods: [
            {
                id: '1',
                name: '黄桃',
                num: 10,
                price: 10,
                isChecked: false,
                imgUrl: '/images/HT.jpg'
            },
            {
                id: '2',
                name: '西瓜',
                num: 20,
                price: 8,
                isChecked: true,
                imgUrl: '/images/XG.jpg'
            },
            {
                id: '3',
                name: '猕猴桃',
                num: 6,
                price: 12,
                isChecked: false,
                imgUrl: '/images/MHT.jpg'
            }
        ],
        isAllChecked: false,
        totalPrice: 0
    },
    onLoad() {
        this.computedTotalPrice()
    },
    // 单选控制全选
    changeCound(e) {
        console.log(e);
        let checkedArr = e.detail.value
        if (checkedArr.length == this.data.goods.length) {
            let goodsList = JSON.parse(JSON.stringify(this.data.goods))
            goodsList.forEach(item => item.isChecked = true)
            this.setData({
                isAllChecked: true,
                goods: goodsList
            })
        } else {
            let goodsList = JSON.parse(JSON.stringify(this.data.goods))
            goodsList.forEach(item => {
                if (checkedArr.includes(item.id)) {
                    item.isChecked = true
                } else {
                    item.isChecked = false
                }
            })
            this.setData({
                isAllChecked: false,
                goods: goodsList
            })
        }
        this.computedTotalPrice()

    },
    // 全选控制单选
    allChecked(e) {
        if (this.data.isAllChecked) {
            let goodsList = JSON.parse(JSON.stringify(this.data.goods))
            goodsList.forEach(item => item.isChecked = false)  //这里是赋值
            this.setData({
                isAllChecked: false,
                goods: goodsList
            })
        } else {
            let goodsList = JSON.parse(JSON.stringify(this.data.goods))
            goodsList.forEach(item => item.isChecked = true)  //这里是赋值
            this.setData({
                isAllChecked: true,
                goods: goodsList
            })
        }
        this.computedTotalPrice()
    },

    // 计算总价
    computedTotalPrice() {
        let totalPrice = this.data.goods.reduce((total, item) => {
            if (item.isChecked) {
                return total + item.num * item.price
            } else {
                return total
            }
        }, 0)
        this.setData({
            totalPrice: totalPrice
        })
    },

    // 加、减、删除
    handle: function (e) {
        let id = e.currentTarget.dataset.id
        console.log(id);
        var index = e.currentTarget.dataset.index
        var val = `goods[${index}].num`
        let oldnum = this.data.goods.find(item => item.id == id).num
        console.log(oldnum);
        if (e.currentTarget.dataset.name == "mulse") {
            let newNum = oldnum - 1
            if (newNum > 0) {
                this.setData({
                    [val]: newNum
                })
            }else if(newNum == 0){
                let goodsList = JSON.parse(JSON.stringify(this.data.goods))
                let newGoodList=goodsList.filter(item=>item.id!==id)
                this.setData({
                    goods:newGoodList
                })
            }
        }else if(e.currentTarget.dataset.name=="add"){
            let newnum=++oldnum
            this.setData({
                [val]:newnum
            })
        }
        this.computedTotalPrice()
    }
})

  • 2
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值