微信小程序使用计算属性computed封装购物车组件

2021-04-11 16:46发布


1.安装计算属性

npm install --save miniprogram-computed
构建npm

2.封装组件cart

cart.js

// components/cart/cart.js
const computedBehavior = require('miniprogram-computed').behavior
Component({
    behaviors: [computedBehavior],
    properties: {
        products: {  // 购物车商品数量
            type: Array,
            value: [],
        }
    },
    data: {
        totalPrice: 0,
        totalNum: 0,
        allChecked: false,
    },
    computed: {
        totalPrice(properties) {
            // 计算总价钱
            let totalPrice = 0;
            properties.products.map((item, index) => {
                item.checked ? totalPrice += parseInt(item.price) * parseInt(item.num) : "";
            })
            return totalPrice;
        },
        totalNum(properties) {
            // 计算总个数
            let totalNum = 0;
            properties.products.map((item, index) => {
                item.checked ? totalNum += parseInt(item.num) : "";
            })
            return totalNum;
        },
        allChecked(properties) {
            // 计算全部状态
            let ind = properties.products.findIndex((item) => {
                return item.checked == false
            })
            if(properties.products.length <=0) return  false;
            return ind == -1 ? true : false;
        }
    },
    methods: {
        desc(e) {
            let {
                index
            } = e.currentTarget.dataset;
            this.properties.products[index].num--;
            if (this.properties.products[index].num <= 1) {
                this.properties.products[index].num = 1;
            }
            this.setData({
                products: this.properties.products
            })
        },
        asc(e) {
            let {
                index
            } = e.currentTarget.dataset;
            this.properties.products[index].num++;
            this.setData({
                products: this.properties.products
            })
        },
        _changeChecked(e) {
            // console.log(e)
            let index = e.currentTarget.dataset.index;
            let val = e.detail.value;
            this.properties.products[index].checked = val;
            this.setData({
                products:this.properties.products
            })
        },
        _changeAllChecked(e){
            let val = e.detail.value;
            this.properties.products.map((item,index)=>{
                this.properties.products[index].checked = val;
            })
            this.setData({
                products:this.properties.products
            })
        },
        // 购物车提交
        formSubmit(){
            var myEventDetail = {
                totalPrice:this.data.totalPrice,
                totalNum:this.data.totalNum
            } // detail对象,提供给事件监听函数
            var myEventOption = {} // 触发事件的选项
            this.triggerEvent('submit', myEventDetail, myEventOption)
        },
        // 购物车删除
        _cartDelete(e){
            let  {id,index} =  e.currentTarget.dataset;
            var myEventDetail = {
               id,index
            } // detail对象,提供给事件监听函数
            var myEventOption = {} // 触发事件的选项
            this.triggerEvent('delete', myEventDetail, myEventOption)
        }
    }

})

cart.wxll

<!-- 购物车列表 -->
<!-- 
    @params
    products     购物车商品   必须
    bindsubmit   结算事件     可选
    binddelete   删除事件     可选
 -->
<view class="container">
    <block wx:for="{{ products }}" wx:key="id">
        <view class="itemlist">
            <switch class="swicth" bindchange="_changeChecked" data-index="{{ index }}" checked="{{ item.checked }}" type="checkbox"></switch>
            <!-- 图片 -->
            <image class="image" src="{{ item.goodspic }}"></image>
            <view class="info">
                <view class="infoaction">
                    <view>{{ item.goodsname }}</view>
                    <view bindtap="_cartDelete" data-id="{{ item.id }}" data-index="{{ index }}">删除</view>
                </view>
               
                <view class="infolist">
                    <view>¥{{ item.price }}</view>
                    <view class="number">
                        <text class="text" bindtap="desc" data-index="{{ index }}" >-</text>
                        <text class="text">{{ item.num }}</text>
                        <text class="text" bindtap="asc" data-index="{{ index }}">+</text>
                    </view>
                </view>
            </view>
        </view>
    </block>
</view>
<view class="bottom">
    <switch type="checkbox" bindchange="_changeAllChecked" checked="{{ allChecked }}" class="bottom-l">全选</switch>
    <view class="bottom-r">
        <view>合计:{{ totalPrice }}</view>
        <view class="jiesuan" bindtap="formSubmit">结算({{ totalNum }})</view>
    </view>
</view>

cart.wxss

/* components/cart/cart.wxss */
.container  .itemlist  .image{
    width: 80px;
    height: 80px;
    flex: 3;
}

.container  .itemlist{
    width: 100%;
    height: 100px;
    border: 1px solid #ccc;
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.container  .itemlist  .switch{
    flex: 1;
}

.container  .itemlist  .info{
    flex: 7;
    margin-left: 20px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    height: 80px;
}
.infolist{
    display: flex;
    justify-content: space-between;
}
.number  .text{
    margin-right: 10px;
}

.bottom{
    width: 100%;
    height: 45px;
    background-color: #123456;
    display: flex;
    justify-content: space-between;
    color: #fff;
    align-items: center;
    position: fixed;
    left: 0;
    bottom: 0;
}

.bottom-l,.bottom-r{
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.jiesuan{
    margin-left: 20px;
}

.infoaction{
    display: flex;
    justify-content: space-between;
    padding-right: 10px;
}

cart.json

{
    "component": true,
    "usingComponents": {}
}

3.参数

| 参数       | 默认值 | 是否必须 | 说明           |

| ---------- | ------ | -------- | -------------- |

| products   | 无     | 是       | 购物车数据     |

| bindsubmit | 无     | 否       | 结算提交事件   |

| binddelete | 无     | 否       | 删除购物车事件 |

4.请求数据格式

 products  数据中,对象内的元素字段必须是当前效果,如果要修改,需要对源码自行修改

products:[{
  // 商品数据格式,源码可根据实际情况更改
  id:2,
  goodsname:"苹果手机",
  goodspic:"/pages/cart/1.jpg",
  num:2,
  price:2000,
  checked:true
 }]

5.事件返回数据

bindsubmit 事件

detail为购物车提交事件,返回的总价钱及总数量

type: "submit"
timeStamp: 6139
target: {id: "", dataset: {…}}
currentTarget: {id: "", dataset: {…}}
mark: {}
detail: {totalPrice: 5000, totalNum: 3}    // 自定义返回数据
touches: undefined
changedTouches: undefined
mut: false
_requireActive: undefined

bindDelete事件

detail为购物车删除事件,返回的是当前删除数据的id和索引位置

type: "delete"
timeStamp: 16480
target: {id: "", dataset: {…}}
currentTarget: {id: "", dataset: {…}}
mark: {}
detail: {id: 1, index: 0}  // 自定义返回数据
touches: undefined
changedTouches: undefined
mut: false
_requireActive: undefined