Several implementations of vue anti-repeat click


foreword

During the project development process, it was found that in the case of fast hand speed, vuethe component click event will be triggered multiple times in succession. This question can produce some unexpected bug.

Below we provide several solutions;


1. Use js anti-shake and Vue custom instructions to realize.

code show as below:

<template>
 <div>
  <div v-debounce="search" style="width: 100px;height: 100px;background-color: yellow;">快速连续点击</div>
 </div>
</template>
<script>
 export default {
    
    
  name: 'debounce',
  data () {
    
    
   return {
    
    
    msg: 'Welcome to Your Vue.js App',
    text: '',
    count: 1
   }
  },
  directives: {
    
    
   debounce: {
    
    
    inserted: function (el, binding) {
    
    
      let timer
      el.addEventListener('click', () => {
    
    
      if (timer) {
    
    
       clearTimeout(timer)
      }
      timer = setTimeout(() => {
    
    
       binding.value()
      }, 300)
     })
    }
   }
  },
  methods: {
    
    
   search () {
    
    
   // 实际要进行的操作
    this.count++
    console.log('count is:' + this.count)
   }
  }
 }
</script>

2. Control the click state

Define a variable (such as: isLock) to control disablethe properties of the button, thereby preventing the user from clicking the button multiple times in a short time

Proceed as follows:

  • First set the variable isLockattribute value falseto make the button clickable ( disable: true)
  • When the user clicks, immediately set the button to be unclickable ( disable: false)
  • After waiting for the event to be executed or the corresponding interval, restore the button to the clickable state

The code is as follows (example):

<el-button @click="clickBtn" :disable="isLock">按钮</el-button>
export default{
    
    
	data(){
    
    
		return {
    
    
			isLock: false, // 控制按钮的disable属性
		}
	},
	methods: {
    
    
		clickBtn(){
    
    
		 	// 设置按钮不可点击(disable: false)
			this.isLock = true
			// 执行耗时间的代码或事件请求等....
			
			// 等待事件执行完或者相应的间隔时间后,恢复按钮为可点击状态
			setTimeout(() => {
    
    
				this.isLock = false
			}, 2000)
		}
	}
}

3. Only use the debounce function

define common.jspublic method file

/**
 * 函数防抖
 */
export function debounce(fn, delay) {
    
    
 // 记录上一次的延时器
 var timer = null;
 var delay = delay || 200;
 return function() {
    
    
  var args = arguments;
  var that = this;
  // 清除上一次延时器
  clearTimeout(timer)
  timer = setTimeout(function() {
    
    
    fn.apply(that,args)
  }, delay);
 }
}

vueComponent introductioncommon.js

import {
    
    debounce} from '../common/common.js'

vuecomponent code

<template>
    <div>
        <div @click="handleClick" style="width: 100px;height: 100px;background-color: yellow;">快速连续点击</div>
    </div>
</template>

<script>
    import {
    
    debounce,throttle} from '../common/common.js'
    export default{
    
    
        data() {
    
    
            return {
    
    
                
            }
        },
        methods:{
    
    
            handleClick:debounce(function(){
    
    
                console.log('业务逻辑')
            },300),
        }
    }
</script>

<style>
</style>


Summarize

existing problems

方法一, 方法三the problems of the two ways

方法一, 方法三The core logic of the two ways is to use debouncethe idea, but the way of use is different.

These two methods can basically meet the needs of preventing repeated clicks, but the actual test found that the delay time is not easy to control. If the delay time is short (<150ms) and quick clicks may still trigger multiple events. If the delay time is long (>600ms), there will be an obvious delay process after the user clicks to trigger the event, and the user experience is not very good.

First, let's define what we want to achieve.

  1. The click event fires immediately when the user presses the button.
  2. Only the first click event is triggered when the user presses the button in rapid succession.
  3. The user clicks the button crazily without interruption (violent test), and only the first event is triggered immediately, and the event will not be triggered during the frantic click, even if the timeout period has passed.

solution

lodashin use debounce;

code show as below:

<template>
    <div>
        <div @click="handleClick" style="width: 100px;height: 100px;background-color: yellow;">快速连续点击</div>
    </div>
</template>

<script>
    import _ from "lodash"
    export default {
    
    
        methods: {
    
    
            handleClick:_.debounce(function() {
    
    
                //你的业务逻辑
                console.log('执行业务逻辑1 ' + Math.random())
            }, 1000, {
    
    
                'leading': true, //在延迟开始前立即调用事件
                'trailing': false, //在延时结束后不调用,保证事件只被触发一次
            })
        }
    }
</script>
<style>
</style>

lodashWhat debounce's 关键配置more leading, you can refer to the official lodashtrailing
documentation for specific explanations about these two attributes .

Guess you like

Origin blog.csdn.net/weixin_48353638/article/details/130201347