本篇博客介绍在微信小程序中实现秒杀功能,本篇博客只介绍微信小程序前端显示效果,后端接口暂不做介绍,效果图如下:
实现该功能的难点是定时器 setInterval 的使用
微信小程序官方文档介绍 setInterval:https://developers.weixin.qq.com/miniprogram/dev/api/base/timer/setInterval.html
在使用完定时器后一定要清除定时器,否则定时器将一直运行,占用程序资源,甚至程序报错。关于有效清除定时器方法在微信开放社区的讨论:https://developers.weixin.qq.com/community/develop/doc/00004485db0170052d6abc12f54400
.wxml代码
<block wx:if="{{isstart}}"> <view class="top"> <view class="imageview"> <image src="/images/background.png" mode="aspectFit"></image> </view> <view class="top_view"> <view class="top_left_view"> <view style="color:red;height:170rpx;line-height:170rpx;margin-top:40rpx;font-size:28rpx"> ¥<text style="font-size:30px">{{list.Money}}</text> {{list.Name}} </view> <view> {{list.Rules[0]}} </view> <view> {{list.Rules[1]}} </view> </view> <view class="top_right_view"> <text>积分兑换</text> </view> </view> </view> <view class="center"> <view style="font-size:34rpx;">积分抢购{{list.Money}}元{{list.Name}}</view> <view style="color:#358174"> <text style="font-size:32rpx">需{{list.Score}}积分 | </text> <text style="font-size:24rpx">每人限抢1次,您已抢购{{list.GetCount}}次</text> </view> <view class="centerview"> <view class="{{list.State==2?'colorred':'colorgray'}}">{{list.StateStr}}</view> <view><text>剩余</text><text style="color:#358174">{{list.LeftCount}}</text><text>份</text></view> </view> </view> <view class="buttom"> <text wx:for="{{list.Info}}" wx:key="key"> {{item}} </text> </view> <block wx:if="{{list.GetCount!=0}}"> <view class="finished"> 您已抢购成功 </view> </block> <block wx:elif="{{list.State==3}}"> <view class="finished"> {{list.Desc}} </view> </block> <block wx:else> <view class="countdownBox" bindtap="nowbuy"> <block wx:if="{{timeout}}"> {{list.Desc}} </block> <block wx:else> <text>倒计时:</text> <view class="item">{{countdown.hour}}</view> <text>:</text> <view class="item">{{countdown.minute}}</view> <text>:</text> <view class="item">{{countdown.second}}</view> </block> </view> </block> </block> <block wx:else> <view class="nostart"> 暂无抢红包活动 </view> </block>
.wxss代码
.top { 100%; height: 380rpx; font-size: 24rpx; border-bottom: 1px solid #989898; } .imageview { 100%; height: 360rpx; } .imageview image { margin-left: 5%; 90%; height: 360rpx; } .top_left_view { 45%; height: 360rpx; margin-left: 21%; margin-top: 20rpx; color: #636365; line-height: 1.5em; margin-top: -360rpx; } .colorgray{ color: gray; } .colorred{ color: red; } .top_left_view view { text-align: center; } .top_right_view { border: 1px solid black; 4%; color: #B89633; height: 200rpx; font-size: 28rpx; margin-top: -300rpx; margin-left: 86%; } .center { 90%; margin-left: 5%; padding: 3% 0; line-height: 1.8em; font-size: 26rpx; border-bottom: 1px solid #989898; } .centerview { display: flex; justify-content: space-between; } .buttom { 90%; margin-left: 5%; font-size: 26rpx; color: #989898; } .finished{ 90%; margin-left: 5%; height: 85rpx; border-radius: 50rpx; background-color: #999999; position: absolute; bottom: 0; margin-bottom: 50rpx; color: white; text-align: center; line-height: 85rpx; } .countdownBox { 90%; margin-left: 5%; height: 85rpx; margin-bottom: 50rpx; background-color: #de2c3a; border-radius: 50rpx; display: flex; justify-content: center; align-items: center; color: #fff; font-size: 30rpx; position: absolute; bottom: 0; } .countdownBox .item{ height: 50rpx; color: #000; box-sizing: border-box; padding: 0rpx 8rpx; display: flex; justify-content: center; align-items: center; font-size: 35rpx; font-weight: 480; margin: 0rpx 10rpx; } .nostart{ text-align: center; margin-top: 200rpx; }
.js代码
var http = require('../../../utils/request.js'); const app = getApp(); Page({ data: { isnull: false, timeout: false, isClicked: true, isstart: false, countdown: { hour: '00', minute: '00', second: '00', millisecond:'00' }, list: [] }, //开始倒计时 startCountdown: function (millisecond) { var that = this; that.clearinterval(); app.globalData.seckillinterval = null; if (millisecond > 0) { app.globalData.seckillinterval = setInterval(function () { millisecond -= 10; if (millisecond <= 0) { if (app.globalData.seckillinterval != null) { clearInterval(app.globalData.seckillinterval); app.globalData.seckillinterval = null; } that.setData({ countdown: { hour: '00', minute: '00', second: '00', millisecond:'00' }, timeout: true }); that.onShow(); } that.transformRemainTime(millisecond); }, 10); } else { that.setData({ timeout: true }); } }, // 剩余时间(毫秒)处理转换时间 transformRemainTime: function (millisecond) { var that = this; var countdownObj = that.data.countdown; var seconds = Math.floor(millisecond / 1000) // 小时 countdownObj.hour = that.formatTime(Math.floor(seconds / 3600 % 24)); // 分钟 countdownObj.minute = that.formatTime(Math.floor(seconds / 60 % 60)); // 秒 countdownObj.second = that.formatTime(Math.floor(seconds % 60)); // 毫秒 countdownObj.millisecond = that.formatTime(Math.floor((millisecond % 1000) / 10)); that.setData({ countdown: countdownObj }); }, //格式化时间为2位 formatTime: function (time) { if (time < 10) return '0' + time; return time; }, //点击“立即抢” nowbuy: function (e) { var that = this; //状态是“秒杀中”才执行方法 if (that.data.list.State == 2 && that.data.isClicked) { that.setData({ isClicked: false }) http.postRequest("Skill/Buy", {}, function (res) { if (res.IsOk) { wx.showModal({ title: '提示', content: res.Data.ErrMsg, showCancel: false, success(res) { if (app.globalData.seckillinterval) { clearInterval(app.globalData.seckillinterval); app.globalData.seckillinterval = null } that.onShow(); } }) } }, function (res) {}) //防止重复提交 setTimeout(function () { that.setData({ isClicked: true }) }, 1000) } }, onShow: function () { var that = this; //获取优惠券信息 http.postRequest("Skill/Index", {}, function (res) { if (res.IsOk) { if (res.Data) { that.setData({ list: res.Data, isstart: true }) that.startCountdown(res.Data.StartTimeLeft) } else { that.setData({ isstart: false }) } } }, function (res) {}) }, //清除计时器 clearinterval: function () { if (app.globalData.seckillinterval) { clearInterval(app.globalData.seckillinterval); app.globalData.seckillinterval = null; } }, onHide: function () { this.clearinterval(); }, onUnload: function () { this.clearinterval(); } })
End!