Recently, I learned vue.js. What impressed me most about the framework was vUE’s componentization and data-driven view rather than directly manipulating the DOM. With JQuery’s fading front-end trend, this UI state change operation is bound to become mainstream. So here’s a small example to illustrate.

Create a button that can be pressed once to clear a single input (or held continuously to clear all input), that is, when a button is pressed (or held), both a function and the input are cleared.

First will start with JS implementation, and then with VUE implementation, in order to highlight the contrast of VUE characteristics

The principle of

To achieve a long press, the user needs to press and hold the button for a few seconds.

To simulate this effect in our code, we need to start a timer to listen for how long the user is pressing the button when the mouse “clicks,” and execute the corresponding function if the time is longer than we expect.

Very simple! However, we need to know when the user is holding down the button.

How to implement

When the user clicks the button, two other events are triggered before the click event: MouseDown and Mouseup.

The MouseDown event is triggered when the user presses the button, and the Mouseup event is called when the user releases the button.

What we need to do is:

  1. When the MouseDown event fires, the timer is started.

  2. Once the Mouseup event is fired 2 seconds before it is expected, clear the timer and do not execute the corresponding function. Think of it as a normal click event.

As long as the timer is not cleared by the time we set it, that is, the mouseup event is not fired — then we can conclude that the user did not release the button. Therefore, it can be judged as a long press that can execute the associated function.

practice

Let’s dive into the code and do just that.

First, we must define three things, namely:

  1. One variable is used to store the timer.

  2. A start function used to start a timer.

  3. A cancellation function used to cancel the timer.

variable

This variable is used to hold the setTimeout value so that we can cancel it when the mouseup event is triggered.

let pressTimer = null;


We set the value of the variable to NULL so that we can check the value of the variable to see if there is a timer running before we cancel.

Start the function

This function includes a setTimeout, which is a basic method in JavaScript that allows a function to be executed after a certain time.

Note that during the execution of the click event, two other events are fired. But it’s the MouseDown event that we need to start the timer. If you just click the event, you don’t need to start the timer.

// Create a timer (execute function after 1s)

let start = (e) => {

// Do not start the timer if it is a click event

if (e.type === ‘click’ && e.button ! = = 0) {

return;

}

// Make sure no timers are running before starting one

if (pressTimer === null) {

pressTimer = setTimeout(() => {

// Execute the task!!

}, 1000).

}

}


Cancel the function

This function is used to cancel the setTimeout created by the start function.

To cancel setTimeout, use the clearTimeout method in JavaScript, which is primarily used to clear the timer set by the setTimeout() method.

Before using clearTimeout, you need to check that the pressTimer variable is null. If not null, it means there is a running timer. Therefore, we need to clear it first and set the pressTimer variable to null.

let cancel = (e) => {

// Check if the pressTimer value is null

if (pressTimer ! == null) {

clearTimeout(pressTimer)

pressTimer = null

}

}

This function is called once the Mouseup event is triggered.

Set trigger

All that remains is to add the event listener to the button you want to long-press.

addEventListener(“mousedown”, start);

addEventListener(“click”, cancel);

Together, the above code looks like this:

// Define variables

let pressTimer = null;

// Create a timer (execute function after 1 second)

let start = (e) => {

if (e.type === ‘click’ && e.button ! = = 0) {

return;

}

if (pressTimer === null) {

pressTimer = setTimeout(() => {

// Execute the task!!

}, 1000).

}

}

// Stop the timer

let cancel = (e) => {

// Check whether a timer is running

if ( pressTimer ! == null ) {

clearTimeout(pressTimer);

pressTimer = null;

}

}

// Select the element whose ID is longPressButton

let el = document.getElementById(‘longPressButton’);

// Add an event listener

el.addEventListener(“mousedown”, start);

// Hold down the event to cancel the timer

el.addEventListener(“click”, cancel);

el.addEventListener(“mouseout”, cancel);

Wrapped with the Vue directive

When creating a Vue directive, you can create global or local directives, and in this article, we use the global directive.

First, we must declare the name of the custom directive.

Vue.directive(‘longpress’, {

})

This registers a global custom directive called V-longpress.

Next, we add the bind hook function with arguments, which allows us to reference the element that the directive is bound to, get the value passed to the directive, and identify the component that the directive uses.

Vue.directive(‘longpress’, {

bind: function(el, binding, vNode) {

}

})

Next, we add the code for the long-press function to the bind function.

Vue.directive(‘longpress’, {

bind: function(el, binding, vNode) {

// Define variables

let pressTimer = null;

// Define the function handler

// Create a timer (execute function after 1 second)

let start = (e) => {

if (e.type === ‘click’ && e.button ! = = 0) {

return;

}

if (pressTimer === null) {

pressTimer = setTimeout(() => {

// Execute the task!!

}, 1000).

}

}

// Cancel the timer

let cancel = (e) => {

// Check whether a timer is running

if ( pressTimer ! == null ) {

clearTimeout(pressTimer);

pressTimer = null;

}

}

// Add an event listener

el.addEventListener(“mousedown”, start);

// Cancel the timer

el.addEventListener(“click”, cancel);

el.addEventListener(“mouseout”, cancel);

}

})

Next, we need to add a function to run the method passed to the Longpress instruction.

Vue.directive(‘longpress’, {

bind: function(el, binding, vNode) {

// Define variables

let pressTimer = null;

// Define the function handler

// Create a timer (execute function after 1 second)

let start = (e) => {

if (e.type === ‘click’ && e.button ! = = 0) {

return;

}

if (pressTimer === null) {

pressTimer = setTimeout(() => {

// Execute the function

handler();

}, 1000).

}

}

// Stop the timer

let cancel = (e) => {

// Check whether a timer is running

if ( pressTimer ! == null ) {

clearTimeout(pressTimer);

pressTimer = null;

}

}

// Run the function

const handler = (e) => {

// Execute the method passed to the instruction

binding.value(e)

}

// Add an event listener

el.addEventListener(“mousedown”, start);

// Cancel the timer

el.addEventListener(“click”, cancel);

el.addEventListener(“mouseout”, cancel);

}

})

Now, you can use this instruction in a Vue application, unless the value passed by the user to the instruction is not a function. Therefore, we need to send warnings to users.

For feedback to the user, we added the following to the bind function:

// Make sure the supplied expressions are functions

if (typeof binding.value ! == ‘function’) {

// Get the component name

const compName = vNode.context.name;

// Pass the warning to the console

let warn = `[longpress:] provided expression ‘${binding.expression}’ is not a function,but has to be `;

if (compName) { warn += `Found in component ‘${compName}’ ` }

console.warn(warn);

}

Finally, it would be great if this directive also worked on touchscreen devices. So we added the TouchStart, TouchEnd, and TouchCancel event listeners.

The final code looks like this:

Vue.directive(‘longpress’, {

bind: function(el, binding, vNode) {

// Make sure the supplied expressions are functions

if (typeof binding.value ! == ‘function’) {

// Get the component name

const compName = vNode.context.name;

// Pass the warning to the console

let warn = `[longpress:] provided expression ‘${binding.expression}’ is not afunction, but has to be `;

if (compName) { warn += `Found in component ‘${compName}’ `}

console.warn(warn);

}

// Define variables

let pressTimer = null;

// Define the function handler

// Create a timer (execute function after 1 second)

let start = (e) => {

if (e.type === ‘click’ && e.button ! = = 0) {

return;

}

if (pressTimer === null) {

pressTimer = setTimeout(() => {

// Execute the function

handler();

}, 1000).

}

}

// Cancel the timer

let cancel = (e) => {

// Check whether the timer has a value

if ( pressTimer ! == null ) {

clearTimeout(pressTimer);

pressTimer = null;

}

}

// Run the function

const handler = (e) => {

// Execute the method passed to the instruction

binding.value(e)

}

// Add an event listener

el.addEventListener(“mousedown”, start);

el.addEventListener(“touchstart”, start);

// Cancel the timer

el.addEventListener(“click”, cancel);

el.addEventListener(“mouseout”, cancel);

el.addEventListener(“touchend”, cancel);

el.addEventListener(“touchcancel”, cancel);

}

})

It can now be used in the Vue component:

<template>

<div>

<button v-longpress=”incrementPlusTen” @click=”incrementPlusOne”>{{value}}</button>

</div>

</template>

<script>

export default {

data() {

return {

value: 10

}

},

methods: {

/ / 1

incrementPlusOne() {

this.value++

},

/ / add 10

incrementPlusTen() {

this.value += 10

}

}

}

</script>