小程序购物车加减和数字输入的组件,及组件向页面、页面向组件传值
一、组件:
1.wxml页面
<!-- 选择数量组件 --> <view class="select"> <text class="reduce {{minusStatus}}" data-num="{{num}}" catchtap="bindMinus" data-price="{{unitPrice}}">-</text> <!-- <input type="number" class="number" data-num="{{num}}" bindinput="getNum" bindblur="getNum" catchtap="empty" value="{{num}}" data-price="{{unitPrice}}" /> --> <view class="number" data-num="{{num}}" catchtap="bindManual" data-price="{{unitPrice}}">{{num}}</view> <text class="add normal" data-num="{{num}}" catchtap="bindPlus" data-price="{{unitPrice}}">+</text> </view> <view class="outBox {{isBox?'show':''}}" catchtap="empty"> <view class="black" catchtap="closeBox"></view> <view class="box"> <text>请输入数量</text> <!-- input输入事件bindinput事件冒泡,此时catchtap给你个空方法,阻止冒泡即可 --> <input type="number" class="number" data-num="{{numNew}}" bindblur="getNum" value="{{numNew}}" catchtap="empty" data-price="{{unitPrice}}" /> <view class="btn"> <view class="cancle" catchtap="closeBox">取消</view> <view class="sure" catchtap="sureBox">确认</view> </view> </view> </view>
2.wxss样式
/** 选择数量组件样式 **/
.select {
bottom: 0;
background: #fff;
padding: 0 20rpx;
font-size: 30rpx;
}
.select .reduce,
.select .add {
float: left;
font-size: 45rpx;
width: 60rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
background-color: #F7F8FA;
}
.select .number {
background-color: #F7F8FA;
float: left;
height: 60rpx;
line-height: 60rpx;
text-align: center;
font-weight: 400;
width: 80rpx !important;
box-sizing: border-box;
margin: 0 2rpx !important;
border: 0 !important;
}
.select .reduce {
border-bottom-left-radius: 8rpx;
border-top-left-radius: 8rpx;
}
.select .add {
border-bottom-right-radius: 8rpx;
border-top-right-radius: 8rpx;
}
/*普通样式*/
.select .normal {
color: #666;
font-weight: normal;
}
/*禁用样式*/
.select .disabled {
color: #ccc;
}
.outBox{
display: none;
}
.show{
display: block;
}
.black{
width: 100%;
height: 100%;
background: rgba(0,0,0,.3);
position: absolute;
top:0;
left: 0;
z-index: 10;
}
.box{
width:75%;
height:280rpx ;
background-color: #fff;
border-radius: 10rpx;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
z-index: 11;
box-sizing: border-box;
padding:45rpx;
}
.box text{
font-size: 16px;
color:#666;
font-weight: 400;
display: block;
width: 100%;
}
.box input{
width:100%;
border:0;
box-sizing: border-box;
text-align: left;
border-bottom:1px solid #ccc;
margin: 20rpx 0;
padding:5px 30rpx;
}
.box .btn {
width: 200rpx;
float: right;
display: flex;
justify-content: space-between;
}
.box .btn .cancle,.box .btn .sure{
display: block;
line-height: 50rpx;
width: 80rpx;
text-align: center;
color:#da2728;
}
3.js
Component({ /** * 组件的初始数据 */ data: { // 数量增减 num: 1, minusStatus: 'disabled', totalPrice: 0, // 定制总价的计算 isBox: false, }, /** * 组件的属性列表 */ properties: { unitPrice: { // 接收传递过来的数据 type: Number, value: 0, }, num: { // 接收传递过来的num type: Number, value: 1, }, tapIndex: { // 点击数量是,当前产品所属的大分类索引 type: Number, value: 0, }, goodIndex: { // 点击时当前购物车产品的索引 type: Number, value: 0, }, cartId: { // 购物车id type: String, }, }, /** * 组件的方法列表 */ methods: { /* 点击减号 */ bindMinus: function () { var num = this.data.num; // 定制页面过来的商品单价 var unitPrice = this.properties.unitPrice; // console.log(unitPrice) // 如果大于1时,才可以减 if (num > 1) { num--; } // 只有大于一件的时候,才能normal状态,否则disable状态 var minusStatus = num <= 1 ? 'disabled' : 'normal'; // 将数值与状态写回 this.setData({ num: num, minusStatus: minusStatus, totalPrice: num * unitPrice, }); // console.log(this.data.totalPrice) // 将数据传递过去 this.triggerEvent("onBindMinus", { "totalPrice": this.data.totalPrice, "num": num, "tapIndex": this.properties.tapIndex, // 购物车分类索引 "goodIndex": this.properties.goodIndex, // 购物车当前产品索引 "cartId": this.properties.cartId, // 当前购物车id }) }, /* 点击加号 */ bindPlus: function (e) { var num = this.data.num; // 定制页面过来的商品单价 var unitPrice = this.properties.unitPrice; // console.log(unitPrice) // 数量最多可以选择9999件 if (num < 9999) { num++; } // 只有大于一件的时候,才能normal状态,否则disable状态 var minusStatus = num < 1 ? 'disabled' : 'normal'; // 将数值与状态写回 this.setData({ num: num, minusStatus: minusStatus, totalPrice: num * unitPrice, }); // console.log(this.data.totalPrice) // 将数据传递过去 this.triggerEvent("onBindPlus", { "totalPrice": this.data.totalPrice, "num": num, "tapIndex": this.properties.tapIndex, // 购物车分类索引 "goodIndex": this.properties.goodIndex, // 购物车当前产品索引 "cartId": this.properties.cartId, // 当前购物车id }) }, /* 点击弹出输入数量 */ bindManual: function (e) { this.setData({ isBox: !this.data.isBox, }) }, // 关闭弹出框和点击取消 closeBox: function (e) { this.setData({ num:this.properties.num, isBox: false, }) }, // 小程序输入框冒泡事件的解决 empty: function (e) { }, // 获取实时输入的数量 getNum: function (e) { var value = e.detail.value; // 定制页面过来的商品单价 var num = e.detail.value; console.log(e.detail.cursor) if(num==0||num==""){ num=1; } this.setData({ newNum:num, }) }, // 确认 sureBox: function (e) { var num = this.data.newNum; if (num == 0||num == '') { this.setData({ num: 1, }) this.properties.num = 1; wx.showToast({ title: '该宝贝不能减少了哦', icon: 'none', }) } this.setData({ isBox: !this.data.isBox, }) var unitPrice = this.properties.unitPrice; this.setData({ totalPrice: num * unitPrice, }) console.log(this.data.totalPrice) // 将数据传递过去 this.triggerEvent("onGetNum", { "totalPrice": this.data.totalPrice, "num": num, "tapIndex": this.properties.tapIndex, // 购物车分类索引 "goodIndex": this.properties.goodIndex, // 购物车当前产品索引 "cartId": this.properties.cartId, // 当前购物车id }) }, }, attached() { // 第二种方式通过组件的生命周期函数执行代码 this.setData({ num: this.properties.num, numNew:this.properties.num, }) // console.log('数量:' + this.properties.num) }, })
二、页面:
1.json文件:
"calculation":"../comment/calculation/calculation",其中calculation是要在页面中引用时用到的标签
{
"navigationBarTitleText":"购物车",
"usingComponents": {
"calculation":"../comment/calculation/calculation",
"login":"../comment/authorize/authorize"
}
}
2.页面
<calculation unitPrice="{{item.price}}" num="{{item.count}}" tapIndex="{{index}}" goodIndex="{{childindex}}" cartId="{{item.id}}" bind:onBindPlus="onBindPlus" bind:onBindMinus="onBindMinus" bind:onGetNum="onGetNum" wx:if="{{item.isChecked}}"> </calculation>
3.js
// 1、点击+数量价格变化
onBindPlus: function (e) {
this.tapCalculation(e);
},
// 2、点击-数量价格变化
onBindMinus: function (e) {
this.tapCalculation(e);
},
// 3、输入数量价格变化
onGetNum: function (e) {
this.tapCalculation(e);
},
// 点击数量更新数据及计算价格
tapCalculation: function (e) {
// console.log(e.detail)
let tapIndex = e.detail.tapIndex; // 点击时大分类索引
let goodIndex = e.detail.goodIndex; // 分类下产品索引
let count = e.detail.num;
let index = e.detail.tapindex;
this.setData({
['cartList[' + tapIndex + '].cartGoods[' + goodIndex + '].totalPrice']: e.detail.totalPrice, // 组件过来的总价
['cartList[' + tapIndex + '].cartGoods[' + goodIndex + '].count']: count,
})
// console.log(this.data.cartList)
this.updateCount(e.detail.cartId, count)
this.calaData()
},
三、传值解析
1.组件向页面传值:
(1)组件js -- this.triggerEvent("页面要用到方法名", {参数});
// 将点击减后的数据传递过去
this.triggerEvent("onBindMinus", {
"totalPrice": this.data.totalPrice,
"num": num,
"tapIndex": this.properties.tapIndex, // 购物车分类索引
"goodIndex": this.properties.goodIndex, // 购物车当前产品索引
"cartId": this.properties.cartId, // 当前购物车id
})
},
// 将输入数字的数据传递过去
this.triggerEvent("onGetNum", { })
// 将点击+号的数据传递过去
this.triggerEvent("onBindMinus", {})
},
(2).页面接收传递过来的值:bind:onBindPlus="onBindPlus" bind:onBindMinus="onBindMinus" bind:onGetNum="onGetNum"
<calculation unitPrice="{{item.price}}" num="{{item.count}}" tapIndex="{{index}}" goodIndex="{{childindex}}" cartId="{{item.id}}" bind:onBindPlus="onBindPlus" bind:onBindMinus="onBindMinus" bind:onGetNum="onGetNum" wx:if="{{item.isChecked}}"> </calculation>
(3).js对处理接收的值
// 点击-数量价格变化
onBindMinus: function (e) {
let tapIndex = e.detail.tapIndex; // 点击时大分类索引
let goodIndex = e.detail.goodIndex; // 分类下产品索引
let count = e.detail.num;
// 取到值再进行相应的价格运算,省略
},
2.页面向组件传值
(1)页面传递值给组件: unitPrice="{{item.price}}" num="{{item.count}}" tapIndex="{{index}}" goodIndex="{{childindex}}" cartId="{{item.id}}" <calculation unitPrice="{{item.price}}" num="{{item.count}}" tapIndex="{{index}}" goodIndex="{{childindex}}" cartId="{{item.id}}" bind:onBindPlus="onBindPlus" bind:onBindMinus="onBindMinus" bind:onGetNum="onGetNum" wx:if="{{item.isChecked}}"> </calculation>
(2)组件接收传递过来的值(用组件的属性列表properties接收,取值时只需要this.properties.unitPrice)
/**
* 组件的属性列表
*/
properties: {
unitPrice: { // 接收传递过来的数据
type: Number,
value: 0,
},
num: { // 接收传递过来的num
type: Number,
value: 1,
},
tapIndex: { // 点击数量是,当前产品所属的大分类索引
type: Number,
value: 0,
},
goodIndex: { // 点击时当前购物车产品的索引
type: Number,
value: 0,
},
cartId: { // 购物车id
type: String,
},
},