需求:使用wx:for渲染一组数据,通过点击计步器减少到0,或者直接输入0,等于删除本条数据。
问题:检测到计步器的value为0时,通过splice()方法删除本条数据后,下一条数据的计步器也变成0,重新赋值也无效。
思路:
1. 考虑到异步变的问题,设置async-change
属性后,通过减少按钮变成0之后删除的数据能正确渲染,但是通过输入0的方式还是有问题。
2. 经过测试,如果删除的数据计数和下一条的数据计数一样,那么删除该条数据后,下一条数据的value就会默认变成0,如果上下两条数据计数不一致,则不影响。
3. 考虑是渲染先后的问题,添加了定时器后再测试,无变化。
4. 根据第2点,改变上下两条数据的值,因为我只要显示整数(所以页面显示不影响)。如果上下两条数据value值相同,则在下一条数据里+0.5后再进行删除。
刚开始目测可行,但是只有第一次时删除时可行,连续删除两条以上同样value值的数据后,下一条数据value依然为0。
5. 既然value值的渲染机制是框架的不可变,那就是只能从渲染顺序入手了。
把需要删除的数据value值变成0,把需要删除的数据过滤后余下数据变成一个新数组,原数组保持不变。
先setData 渲染一遍原数组,目的是把value变成0之后先显示在页面,然后再setData渲染一遍新数组,这样数据就能正常显示了。
小bug:该办法只适用于数据不算多的情况下。不过为零删除的场景一般适用于备选购物车的情况,所以能满足绝大部分的场合需求。
代码
wxml :
<scroll-view scroll-y="true" style="min-height:300px;max-height: 60%;">
<block wx:if="{{shoppingCart.length > 0}}" wx:for="{{shoppingCart}}">
<view class="actionSheet-item" >
<view class="custom-flex-row-start">
<image src="{{item.GoodPictureURL}}" mode="widthFix">
</image>
<view class="box-item-textBox ">
<text style="font-size: 30rpx;">{{item.GoodName}}</text>
<view style="font-size: 24rpx;">回购积分:{{item.Point}}</view>
</view>
</view>
<van-stepper id="{{index}}" value="{{ item.tepperNumber}}" integer="{{true}}" min="0" max="100"
bind:change="onStepperCheck" bind:blur="blurStepperCheck" async-change
bind:focus="focusStepperCheck" button-size="21px" integer="{{true}}" />
</view>
</block>
<view wx:if="{{shoppingCart.length == 0}}" class="actionSheet-noneCar">
<image src="../../../utils/images/shopping_car.png" mode="widthFix"></image>
<text>您还没有选择礼品哦~</text>
</view>
</scroll-view>
js
//购物车计件-失去焦点
blurStepperCheck(e) {
console.log("失焦时",e.detail.value)
if(e.detail.value != 0){
this.setData({
focusTag: false,
})
return
}else{
let index = Number(e.target.id)
let pointSum = this.data.pointSum - this.data.shoppingCart[index].Point * this.data.shoppingCart[index].tepperNumber
let shoppingCart = this.data.shoppingCart
shoppingCart[index].tepperNumber = e.detail.value
console.log(shoppingCart, shoppingCart[index])
let newArr = shoppingCart.filter((value,indexV)=>{
return indexV != index
})
this.setData({
shoppingCart: shoppingCart,
pointSum:pointSum,
})
this.setData({
shoppingCart: newArr,
})
}
},
//购物车计件-聚焦时触发
focusStepperCheck(e) {
// console.log("聚焦时")
this.setData({
focusTag: true,
})
},
//购物车-计步器
onStepperCheck(e) {
console.log("开始e.detail=", e.detail, )
let index = Number(e.target.id)
//判断是否为0-9
let tag = /^([0-9][0-9]*)$/.test(Number(e.detail))
console.log(tag, this.data.focusTag)
//输入非数字时
if (!tag) {
return
}
//聚焦时输入0时
if (this.data.focusTag && e.detail == 0) {
return
}
//防止清空时报错
if (this.data.shoppingCart.length == 0) {
return
}
console.log('id=', index)
// return
let update = 'shoppingCart[' + index + ']' + '.tepperNumber' //拼接字符窜
let tepperNumber = this.data.shoppingCart[index].tepperNumber
console.log('e.detail=', e.detail, 'tepperNumber=', tepperNumber)
if (e.detail == 0) {
//如果为0,就删除
console.log(this.data.shoppingCart[index])
let pointSum = this.data.pointSum - this.data.shoppingCart[index].Point * this.data.shoppingCart[index].tepperNumber
let shoppingCart = this.data.shoppingCart
shoppingCart.splice(index, 1)
console.log(shoppingCart, )
this.setData({
shoppingCart: shoppingCart,
pointSum: pointSum,
})
// console.log(this.data.shoppingCart[index])
} else if (e.detail > tepperNumber) {
// 大于就添加积分
console.log(this.data.shoppingCart[index])
let pointSum = this.data.pointSum + this.data.shoppingCart[index].Point * (e.detail - tepperNumber)
this.setData({
[update]: e.detail,
pointSum: pointSum,
})
} else if (e.detail < tepperNumber) {
// 小于就减少积分
let pointSum = this.data.pointSum - this.data.shoppingCart[index].Point * (tepperNumber - e.detail)
this.setData({
[update]: e.detail,
pointSum: pointSum,
})
}
},