今天测试在测试小程序时,提了一个bug,真机测试的时候,快速点击tab切换时,会出现下面的swiper-item中的内容快速闪烁,无法停止的情况。想了很久也上网查了大量资料,最后突然想起来好像与防抖和节流有关,于是…
函数防抖:
英文 debounce 有防反跳的意思,大致就是指防止重复触发。
那么,函数防抖,真正的含义是:延迟函数执行。即不管debounce函数触发了多久,只在最后一次触发debounce函数时,才定义setTimeout,到达间隔时间再执行 需要防抖的函数。
用处:多用于 input 框 输入时,显示匹配的输入内容的情况。
函数节流:
英文 throttle 有节流阀的意思。大致意思也是 节约触发的频率
那么,函数节流,真正的含义是:单位时间n秒内,第一次触发函数并执行,以后 n秒内不管触发多少次,都不执行。直到下一个单位时间n秒,第一次触发函数并执行,这个n秒内不管函数多少次都不执行。
用处:多用于页面scroll滚动,或者窗口resize,或者防止按钮重复点击等情况
在小程序中,函数防抖、函数节流的使用方式:
一般都会把这两种方法封装在公用的 js 中:
tool.js:
/*函数节流*/
function throttle(fn, interval) {
var enterTime = 0;//触发的时间
var gapTime = interval || 300 ;//间隔时间,如果interval不传,则默认300ms
return function() {
var context = this;
var backTime = new Date();//第一次函数return即触发的时间
if (backTime - enterTime > gapTime) {
fn.call(context,arguments);
enterTime = backTime;//赋值给第一次触发的时间,这样就保存了第二次触发的时间
}
};
}
/*函数防抖*/
function debounce(fn, interval) {
var timer;
var gapTime = interval || 1000;//间隔时间,如果interval不传,则默认1000ms
return function() {
clearTimeout(timer);
var context = this;
var args = arguments;//保存此处的arguments,因为setTimeout是全局的,arguments不是防抖函数需要的。
timer = setTimeout(function() {
fn.call(context,args);
}, gapTime);
};
}
export default {
throttle,
debounce
};
函数节流的说明:
(1) 第一次执行时,是一定能执行函数的。
(2) 然后 n秒内第二次触发的时候,当第一次与第二次间隔不足 设置的间隔时间时,就不会执行。之后第三、第四次触发还是不执行。
(3) 直到 n秒之后 有且仅有一次,并且是第一次再次触发函数。
函数防抖的说明:
(1) 第一次触发函数时,定义了一个定时器。在 n秒后执行。
(2) 然后 函数第二次触发的时候,由于闭包的特性,这时候的 timer已经是第一次触发时的 定时器的标识了。然后直接清除第一次的setTimeout,这时候第一次的setTimeout里面的内容就不会执行了。然后再定义第二次的setTimeout。
(3) 然后重复第二个步骤,一直清除,又一直设置。直到函数最后一次触发,定义了最后的一个定时器,并且间隔 n秒 执行。
(4) 如果在 最后一个定时器没执行时,函数又触发了,那么又重复第三步。相当于 设置的间隔时间,只是延迟函数执行的时间,而不是间隔多少秒再执行。
到这里,这两个方式的区别就很明显了。函数节流是减少函数的触发频率,而函数防抖则是延迟函数执行,并且不管触发多少次都只执行最后一次。
使用:(不知道为什么要写e[0]才行,求解)
import tool from "../../../utils/tool.js";
/*点击切换*/
clickTab: tool.throttle(function(e) {
var _this = this;
if (this.data.currentTab === e[0].currentTarget.dataset.current) {
return false
} else {
this.setData({
currentTab: e[0].currentTarget.dataset.current
})
}
}),
/*滑动切换*/
bindChange(e) {
var _this = this;
this.setData({
currentTab: e.detail.current
})
},
下面是完整代码:
html:
<view style='height:20rpx;background:#f0f0f0'></view>
<!-- 选项卡 -->
<view class="swiper-tab">
<view class="swiper-tab-item {{currentTab==0?'active':''}}" data-current="0" bindtap="clickTab">
<image wx:if="{{currentTab==0}}" class='image1' src='../../../images/home/guanhuai.png'></image>
<image wx:else class='image1' src='../../../images/home/guanhuaian.png'></image>
<text>领导关怀</text>
</view>
<view class="swiper-tab-item {{currentTab==1?'active':''}}" data-current="1" bindtap="clickTab">
<image wx:if="{{currentTab==1}}" class='image2' src='../../../images/home/zhidu.png'></image>
<image wx:else class='image2' src='../../../images/home/zhiduan.png'></image>
<text>制度规范</text>
</view>
<view class="swiper-tab-item {{currentTab==2?'active':''}}" data-current="2" bindtap="clickTab">
<image wx:if="{{currentTab==2}}" class='image3' src='../../../images/home/gonggao.png'></image>
<image wx:else class='image3' src='../../../images/home/gonggaoan.png'></image>
<text>市场公告</text>
</view>
</view>
<!-- 选项卡内容 -->
<swiper current='{{currentTab}}' duration="{{300}}" style="height:90vh" bindchange="bindChange">
<swiper-item>
<block wx:if="{{messageData.length == 0}}">
<view class='zanwu'>暂无数据</view>
</block>
<scroll-view scroll-y="{{true}}" style="height:100%">
<block wx:for="{{messageData}}" wx:key="{{index}}">
<view class='message_item space_between' data-item="{{item}}" bindtap='goDetail'>
<image wx:if='{{item.imgUrl}}' class='item_image' src='{{item.imgUrl}}'></image>
<image wx:else class='item_image' src='/images/home/zhanwei.png'></image>
<view class='item_right'>
<view class='item_title'>{{item.title}}</view>
<view class='item_date'>{{item.date}}</view>
</view>
</view>
</block>
</scroll-view>
</swiper-item>
<swiper-item>
<block wx:if="{{messageData2.length == 0}}">
<view class='zanwu'>暂无数据</view>
</block>
<scroll-view scroll-y="{{true}}" style="height:100%">
<block wx:for="{{messageData2}}" wx:key="{{index}}">
<view class='message_item space_between' data-item="{{item}}" bindtap='goDetail'>
<image wx:if='{{item.imgUrl}}' class='item_image' src='{{item.imgUrl}}'></image>
<image wx:else class='item_image' src='/images/home/zhanwei.png'></image>
<view class='item_right'>
<view class='item_title'>{{item.title}}</view>
<view class='item_date'>{{item.date}}</view>
</view>
</view>
</block>
</scroll-view>
</swiper-item>
<swiper-item>
<block wx:if="{{messageData3.length == 0}}">
<view class='zanwu'>暂无数据</view>
</block>
<scroll-view scroll-y="{{true}}" style="height:100%">
<block wx:for="{{messageData3}}" wx:key="{{index}}">
<view class='message_item space_between' data-item="{{item}}" bindtap='goDetail'>
<image wx:if='{{item.imgUrl}}' class='item_image' src='{{item.imgUrl}}'></image>
<image wx:else class='item_image' src='/images/home/zhanwei.png'></image>
<view class='item_right'>
<view class='item_title'>{{item.title}}</view>
<view class='item_date'>{{item.date}}</view>
</view>
</view>
</block>
</scroll-view>
</swiper-item>
</swiper>
css:
/* details/home/marketInfo/marketInfo.wxss */
page {
background: #fff;
}
.swiper-tab {
width: 100%;
text-align: center;
height: 78rpx;
line-height: 78rpx;
display: flex;
flex-flow: row;
justify-content: space-between;
background: #f9f9f9;
margin-top: 10rpx;
}
.swiper-tab-item {
width: 33.33%;
display: flex;
align-items: center;
justify-content: center;
}
.swiper-tab-item image {
margin-right: 14rpx;
}
.swiper-tab-item image.image1 {
width: 29rpx;
height: 32rpx;
}
.swiper-tab-item image.image2 {
width: 25rpx;
height: 31rpx;
}
.swiper-tab-item image.image3 {
width: 30rpx;
height: 31rpx;
}
.swiper-tab-item text {
color: #060606;
font-size: 30rpx;
display: inline-block;
height: 100%;
position: relative;
}
.swiper-tab-item.active text {
color: #50b2fa;
/* border-bottom: 4rpx solid #F65959; */
font-size: 30rpx;
font-weight: bold;
}
.swiper-tab-item.active text::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
width: 58rpx;
height: 3rpx;
background: linear-gradient(0deg, rgba(29, 188, 229, 1) 0%, rgba(51, 205, 169, 1) 100%);
}
swiper-item {
width: 100%;
box-sizing: border-box;
padding: 24rpx 50rpx;
}
.message_item {
padding: 28rpx 20rpx;
background: #f4f4f4;
margin-bottom: 28rpx;
border-radius:0px 30rpx 30rpx 0px;
align-items: center;
}
.item_image {
width: 135rpx;
height: 100rpx;
margin-right: 30rpx;
border-radius: 10rpx;
}
.item_right {
width: 445rpx;
}
.item_title {
font-size: 28rpx;
height: 80rpx;
color: #060606;
/* margin-bottom: 20rpx; */
display: -webkit-box;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
}
.item_date{
font-size:26rpx;
color: #999999
}
/*暂无数据*/
.zanwu {
text-align: center;
color: #b3b3b3;
margin-top: 20rpx;
font-size: 26rpx;
}
js:
// details/home/marketInfo/marketInfo.js
import {
wxRequest
} from "../../../utils/util.js"
import {
loginCheck
} from "../../../utils/filter.js"
import tool from "../../../utils/tool.js";
Page(loginCheck({
/**
* 页面的初始数据
*/
data: {
currentTab: 0,
messageData: [],
messageData2: [],
messageData3: [],
},
/*点击切换*/
clickTab: tool.throttle(function(e) {
var _this = this;
if (this.data.currentTab === e[0].currentTarget.dataset.current) {
return false
} else {
this.setData({
currentTab: e[0].currentTarget.dataset.current
})
}
}),
/*滑动切换*/
bindChange(e) {
var _this = this;
this.setData({
currentTab: e.detail.current
})
},
goDetail(e) {
let id = JSON.stringify(e.currentTarget.dataset.item.id);
wx.navigateTo({
url: '../marketInfo-details/marketInfo-details?id=' + id,
success: function(res) {},
fail: function(res) {},
complete: function(res) {},
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
this.loadData("领导关怀");
this.loadData("制度规范");
this.loadData("市场公告");
},
loadData(tabTitle = "领导关怀") {
let param = {};
param.n_type = tabTitle;
param.page = 1;
param.row = 10;
wx.showLoading({
title: '玩命加载中...',
})
wxRequest("/admin/notice/notice_info/getTitleList", param, "GET").then(res => {
// var data = this.data.messageData;
if (res.data.status == 1) {
var arr = res.data.data.map(item => {
return {
imgUrl: item.img,
title: item.title,
date: item.date,
id:item.id
}
})
if (tabTitle == "领导关怀"){
this.setData({
messageData: arr
})
} else if (tabTitle == "制度规范"){
this.setData({
messageData2: arr
})
} else if (tabTitle == "市场公告"){
this.setData({
messageData3: arr
})
}
wx.hideLoading()
}
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function() {
}
}))