一、场景分析
一个很常见的场景:由于网络或者后台处理速度的原因,用户操作发出的请求无法得到快速响应,这个时候用户多半会以为没有点击成功或者因为没有耐心而去再次点击按钮。一般来说,这种重复请求会在后端进行过滤,但是只靠后端无法保证能够处理所有的意外情况,所以最好在前端也加以限制。那么问题来了,全站可能有几十上百个按钮,该如何进行限制?
二、解决方案
1. 方案一
给每个按钮绑定一个变量,在按钮绑定的函数请求发出时置灰按钮,在请求获得结果的回调中更改变量的值使按钮重新可用。这是最容易想到的方法,也是实现起来最简单但是工作十分繁琐的方法,代码组织结构较差,扩展性弱。
2. 方案二
这个方案是相对于方案一的改进,但只是略有改善。方案一中有多少个按钮就设置多少个变量分别与之对应,方案二中则只使用一个全局的变量,所有按钮都通过修改这个变量的值来禁用自身及其他按钮。也就是说,点击了一个按钮没有返回值的话,那么同页面的其他按钮也无法点击。为了让这个操作看起来更合理,可以在请求处理期间为页面添加一个小小的loading 图,我看到ios 系统中的很多设置功能就是这样实现的。
这个方案使得我们管理的变量会少很多,但是依然要在每个请求回调的函数中操作变量以更改其状态,且变量的减少付出了增加按钮之间耦合性的代价。
3. 方案三(完美)
这个方案是从一个前端群里的热心同行口中得知的,以Vue 指令的方式实现,代码如下:
组件中的html
<v-btn
v-btn-control="create"
</v-btn>
组件中的js 方法
create() {
return this.axios.post(url, data)
.then((res) => {
if (res.data.errcode == 0) {
// success
} else {
// fail
}
}).catch((err) => {
// console.log(err);
});
}
Vue 全局指令
// 限制按钮点击事件,在结果返回以前不能继续点击
Vue.directive("btn-control", {
// 插入dom 时做的事情
inserted: function(el, bind) {
el.addEventListener("click", () => {
el.disabled = true;
bind.value().then(res => {
el.disabled = false;
});
});
}
});
代码很简单,也不用解释,看几遍就吉道廖。简单画个图,便于理解。