SoFunction
Updated on 2025-04-10

Explanation of the attempt to prevent repeated clicks from happening

Introduction: As the projects you come into contact with increase, many projects encounter the same problem, and each time they use the usual methods to deal with it. Sometimes some methods are not so elegant or even a little redundant, so I also want to start trying different methods to solve the same problem.

I often encounter repeated clicks of the form after repeated clicks of buttons in projects. So I tried several ways to solve this problem separately. Directly upload the code.

1. Rough and simple method

Directly define a variable, and release the variable after each click after all operations are finished. Or use loading to prevent users from clicking

//* Partial code<script>
export default {
  methods: {
    onSubmit() {
      if () return;
       = true;
      // const load = this.$loading();
      this.$().then((res) => {
        // do something
         = false;
        // ();
      }).catch(() => {
         = false;
        // ();
      })
    }, 
  },
}
</script>

This method is simple and crude, but every time you need to prevent repeated clicks, you have to pay attention to the reset of lock or loading, which always feels very long-winded. There is no way to get out properly. (PS: Limited ability, I didn't think of a better way to elegantly encapsulate it on the upper layer)

2. Put loading directly into http request and unify the encapsulation method

//* Partial code...
let load;
((config) => {
  load = Loading();
  ...
  return config;
}, error => {
  ();
  return (error)
});

((response) => {
  ();
  ...
  return response; 
},error => {
  ();
  return (error);
});

This method has been used for a while in practice and was very useful at the beginning, but when I tested it later, I found that it would also lead to repeated clicks. Moreover, sometimes the loading diagram is not required for all requests, and you also need to make a configuration for whether to display loading. This makes the http request feel bulky again, and the repeated click function is not removed.

3. Decorator method

Speaking of decorators, the most classic application scenario is slice programming (AOP), "Frequently used design patterns (1)--Decorator)"/post/5cb415... I have made a great understanding and application. Thanks to ES7 and TS, decorators have many cases in Angular and react. Because Class is not a necessary choice in Vue, it is rare to see decorators in Vue. Thanks to the official method of using vue-class-component to create components using Class, I started my own attempt.

export function lock(target, key, desc) {
  const fn = ;
  //* The arrow function is not used to make this signifier return to vue, so that the data of vue can be obtained and more things will be done below.   = async function() {
    if (this.$lock) return;
    this.$lock = true;
    await (this).catch(() => {
      this.$lock = false;
    });
    this.$lock = false;
    return target;
  };
}

<template>
  <!-- do something -->
</template>
<script>
import Vue from 'vue';
import Component from 'vue-class-component';
import { lock } from './lock';

@Component
export default class extends Vue {
  @lock
  async onSubmit() {
    await this.$();
    // do something
  }
}
</script>

I feel that this is completely removed from the repeated click function (PS: it seems like this), and can also be tested independently, and use it wherever you want. What feels insufficient is that this needs to be pointed back to vue in the decorator to obtain vue's data

4. Learn from one example and apply it to others

Since repeated clicks can be extracted from the business code, the field verification of our submitted form can also be extracted. (PS: All UI frameworks have mature form form verification components, just think I'm just messing around)

export function validate(target, key, desc) {
 const fn = ;

  = async function () {
  const {
   name, phone,
  } = ;
  
  if (!name) {
   return confirm('Please enter your name');
  }
  if ( &gt; 20) {
   return confirm('Your name cannot exceed 20 words');
  }
  if (!phone) {
   return confirm('Please enter your phone number');
  }
  if (!((/^\d{11}$/.test(phone)))) {
   return confirm('Please enter the 11-digit phone number');
  }
  
  await (this);
  return target;
 };
}

<template>
  <!-- do something -->
</template>
<script>
import Vue from 'vue';
import Component from 'vue-class-component';
import { validate } from './validate';

@Component
export default class extends Vue {
  data = {
    name: '',
    phone: '',
  }
  
  @validate
  async onSubmit() {
    await this.$();
    // do something
  }
}
</script>

5. Anti-shake method (supplement)

Some friends said that anti-shake can be used, but I personally think that you still need to look at the scene, so here is a list of anti-shake methods.

The anti-shake method is a good way to limit the frequent triggering of repeated events. It is often used on scroll and resize events, and can also be tried to use on repeated clicks. However, if there is asynchronous processing after clicking events, using the anti-shake method alone will not be able to limit the situation of repeated clicks under weak networks (PS: complain about the fact that mobile networks on Chengdu subway are often not good). For example: the anti-shake time is 1 second, but the request took 2 seconds to return the data to the front end for processing, and a time difference occurred in the middle, causing the user to have time to click repeatedly. So I personally think that it is necessary to cooperate with other methods. Also list the anti-shake columns:

const throttle = function(fn, wait, scope) {
  clearTimeout();
   = setTimeout(function() {
    (scope);
  }, wait);
};

<template>
  <!-- do something -->  
</template>
<script>
export default {
  onSubmit() {
    throttle(() => {
      this.$().then((result) => {
        // do something
      });
    }, 1000);
  },
};
</script>

The above is a detailed explanation and integration introduced by the editor to prevent repeated clicks of buttons. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support for my website!