微信小程序按钮防抖节流设计新思路
...大约 3 分钟微信小程序miniprogram
前言
在现在的业务开发中有很多需要用户主动操作的按钮,比方说提交订单,加入购物车等
这些场景在网路波动时候,服务端响应慢的话可能造成用户感知不强,用户不知道是否成功就会
导致用户短时间内多次点击,那么在前端有一些解决方案的那就是防抖和节流。
解决方案
方案一
防抖和节流的区别
防抖和节流的区别在于触发事件的时间,防抖是当事件触发n秒后才执行回调,节流是当事件触发n秒内只执行一次回调。
防抖和节流的应用场景也不一样,防抖适用于用户输入,节流适用于用户操作频繁的场景。
节流
节流就是在一段时间内,只能触发一次事件,如果在这段时间内又触发了事件,则在这段时间内忽略
这次事件,直到这段时间结束后,才能再次触发事件。
function throttle(fn, delay) {
let timer = null;
return function () {
let context = this;
let args = arguments;
if (!timer) {
timer = setTimeout(function () {
fn.apply(context, args);
timer = null;
}, delay);
}
}
}
防抖
防抖就是在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
function debounce(fn, delay) {
let timer = null;
return function () {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
}
}
防抖和节流的应用场景
防抖和节流的应用场景也不一样,防抖适用于用户输入,节流适用于用户操作频繁的场景。但是这些都是js层面中断了操作,并不是真正的阻塞用户的操作,所以在实际开发中,我们需要结合业务场景来选择使用。
方案二
该方案是利用小程序的wxs
方法实现的。
具体原理就是在wxs
中触发点击的时候,给当前节点下边添加一个node
,这个node
这个节点的大小
跟按钮一模一样,层级设置为-1,当点击时候开始执行动画,此时 层级变成1,覆盖在点击元素上方
此时重复点击,实际上点击的并不是目标元素,
在指定时间内动画,当动画执行完毕拿到回调,再次改node
层级为-1,代码如下:
<!--basic-components/debounceElement/index.wxml-->
<wxs module="tool" src="./index.wxs"></wxs>
<view class="debounce-content" capture-bind:tap="{{tool.tap}}">
<view class="debounce-mark"
style="--debounce-time: {{time}}s"
bind:animationend="{{tool.end}}"
>
</view>
<slot/>
</view>
// basic-components/debounceElement/index.js
Component({
/**
* 组件的属性列表
*/
properties: {
time: { // isPromise为false时生效
type: Number,
value: 1
},
},
})
wxs代码如下
// basic-components/debounceElement/index.wxs
function tap(event, ownerInstance) {
var instance = ownerInstance.selectComponent('.debounce-mark');
instance && instance.addClass && instance.addClass('loading');
}
function end(event, ownerInstance) {
var instance = ownerInstance.selectComponent('.debounce-mark');
instance && instance.removeClass && instance.removeClass('loading');
}
module.exports = {
tap: tap,
end: end
}
重点是下边样式代码
/* basic-components/debounceElement/index.wxss */
.debounce-content {
width: fit-content;
height: fit-content;
position: relative;
}
.debounce-mark {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
background: transparent;
z-index: -1;
}
.loading::before {
content: attr(data-text);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #999;
}
.loading {
/*动画执行时间 极为节流间隔时间*/
animation: run var(--debounce-time) step-end;
animation-fill-mode: forwards;
}
@keyframes run {
from {
z-index: 1;
}
to {
z-index: -1;
}
}
使用方法
<debounce-element>
<button block="{{true}}" bindtap="onSendRequest">发送请求</button>
</debounce-element>
<!--此时这个onSendRequest方法会在1s内只触发一次-->
以上可以使用一个动画演示:
请注意,红色方块 即为重点
对比
方案一
- 是在js执行,需要监听回调函数,比较通用
方案二
- 利用小程序的
wxs
方法实现,可以直接在wxml中触发事件,不需要监听回调函数
Powered by Waline v2.15.8