100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Vue 项目中 点击多次按钮禁止重复提交数据

Vue 项目中 点击多次按钮禁止重复提交数据

时间:2019-11-26 12:27:12

相关推荐

Vue 项目中 点击多次按钮禁止重复提交数据

为了阻止用户在某些情况下,短时间内重复点击某个按钮,导致前端向后端重复发送多次请求。

方法一:

通过控制 loading 来设置 loading,或者 disabled 也行,从而来控制按钮的是否可以点击。通过在 handleSubmit 函数未获取到服务器接口响应之前,该按钮一直处于不可用的状态,直到接收到服务器接口相应后,我们再将按钮恢复为可用状态。

<el-button type="primary" class="w312" :loading="loading" @click="handleSubmit">登录</el-button>handleSubmit () {this.loading = truesetTimeout(() => {this.loading = false}, 1000)}// 或者handleSubmit () {if (timer) {clearTimeout(timer)}timer = setTimeout(() => {this.submit()}, 300)}

进阶版:

export const operationConfirm = function (attr, message) {const that = thisreturn new Promise((resolve, reject) => {that.$antdConfirm({title: '提示',content: message || `确定要执行${attr}操作吗?`,onOk () {resolve(true)},onCancel () {resolve(false)},})})}// loading 处理重复提交(注意 Vue 实例上添加 submitLoading 字段)export const handleRepeatSubmit = async function (message, fn, cb, loading = 'submitLoading') {if (!fn) returnconst confirm = message && await operationConfirm.call(this, message)const that = thisif (!message || confirm) {if (that[loading]) returnthat[loading] = truetry {const data = await fn()cb && cb(data)that[loading] = false} catch (error) {that[loading] = false}}}// 使用如下, fn 为接口调用async handleConfirm () {const { validate, form } = this.$refs.cancelif (!await validate()) {return}handleRepeatSubmit.call(this, null, () => fn(), () => {this.visible = falsethis.$antdMessage.success('操作成功')this.$emit('refresh')})},

方法二:

使用 axios 第三方库,request 拦截器来拦截重复请求。

更多详情,请查看:axios 全局阻止重复请求。

方法三:

为避免用户在短时间内点击过快,我们给点击设置点击间隙,即做防抖处理。其实就是比较当前点击和上一次点击的时间差,如果时间差小于设置的值,即阻止点击事件,同时记录这次点击事件,以便和下次点击做比较。了解防抖基础知识,请查看:防抖和节流的区别以及实现。

// 防抖export const antiShake = (fn, t) => {let delay = t || 500let timerreturn function () {let args = arguments;if (timer) clearTimeout(timer) let callNow = !timer timer = setTimeout(() => {timer = null}, delay)if (callNow) fn.apply(this, args)}}

如何使用呢?

//引入防抖文件import { antiShake } from '@/utils/utils.js'; // 给按钮添加防抖startDrawPolygon:antiShake(function(){......})

进阶一:

除了上述实现方案,我们也可以自定义指令来实现点击事件防抖功能。

Vue.directive('antiShake', {// 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。/*** el 指令所绑定的元素,可以用来直接操作 DOM 。* binding 一个对象,包含绑定的值*/inserted: function(el, binding) {const { callback, time } = binding.valueel.callback = callbackel.time = timeel.timeCall = nullel.addEventListener('click', () => {clearTimeout(el.timeCall)el.timeCall = setTimeout(() => {el.callback()}, el.time || 500)})},......})

通过定时器 setTimeout 延时执行 click 回调,当 el.time || 500 时间内,再次触发 clearTimeout 清除定时器;

Vue.directive('antiShake', {......// 所在组件的 VNode 更新时调用update: function(el, binding) {console.log('update')const { callback, time } = binding.valueel.callback = callbackel.time = time},})

更新挂载到 el 上的 callback 和 time ,当 v-antiShake 绑定的值更新后,事件触发跟新后的 callback。

如何使用呢?

<button v-antiShake="handleClick">click</button>handleClick: {time: 1000,callback: () => {console.log(1111)}}

指令的值 handleClick 未作深度监听(watch 之 deep),只有对象整体改变才会触发指令中的 update 钩子函数。

进阶二:

当然我们全局配置防抖,即把 click 添加的防抖处理事件,添加到 Vue 实例上。

const on = Vue.prototype.$on// 防抖处理Vue.prototype.$on = function (event, func) {let timerlet newFunc = funcif (event === 'click') {newFunc = function () {clearTimeout(timer)timer = setTimeout(function () {func.apply(this, arguments)}, 500)}}on.call(this, event, newFunc)}

参考案例:

vue全局配置防抖和节流

防抖与节流(vue-自定义指令)

vue 自定义防抖/节流指令的实现

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

更新

使用 lodash 库的 debounce 来配置防抖功能。

待完善.......

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。