zoukankan      html  css  js  c++  java
  • Vue实现长按事件

    参考:https://blog.logrocket.com/building-a-long-press-directive-in-vue-3408d60fb511/

    废话不多说,直接上代码:

    1. 注册自定义指令

    Vue.directive('longpress', {
        bind: function (el, binding, vNode) {
            // Make sure expression provided is a function
            if (typeof binding.value !== 'function') {
                // Fetch name of component
                const compName = vNode.context.name
                // pass warning to 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)
            }
    
            // Define variable
            let pressTimer = null
    
            // Define funtion handlers
            // Create timeout ( run function after 1s )
            let start = (e) => {
    
                if (e.type === 'click' && e.button !== 0) {
                    return;
                }
    
                if (pressTimer === null) {
                    pressTimer = setTimeout(() => {  // 如果要在按住按钮的时候循环行一个函数,将setTimeout改为setInterval即可
                        // Run function
                        handler()
                    }, 1000)
                }
            }
    
            // Cancel Timeout
            let cancel = (e) => {
                // Check if timer has a value or not
                if (pressTimer !== null) {
                    clearTimeout(pressTimer)
                    pressTimer = null
                }
            }
            // Run Function
            const handler = (e) => {
                binding.value(e)
            }
    
            // Add Event listeners
            el.addEventListener("mousedown", start);
            el.addEventListener("touchstart", start);
            // Cancel timeouts if this events happen
            el.addEventListener("click", cancel);
            el.addEventListener("mouseout", cancel);
            el.addEventListener("touchend", cancel);
            el.addEventListener("touchcancel", cancel);
        }
    })

    2. 组件中使用

    <template>
        <div>
            <button v-longpress="incrementPlusTen" @click="incrementPlusOne">{{value}}</button>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                value: 10
            }
        },
        methods: {
            // Increment value plus one
            incrementPlusOne() {
                this.value++
            },
            // increment value plus 10
            incrementPlusTen() {
                this.value += 10
            }
        }
    }
    </script>

    原文:

    Have you ever wanted to execute a function in your Vue application just by holding a button down for a few seconds?

    Have you ever wanted to create a button on your application that helps to clear out either a single input by pressing once (or a whole input holding a button down)?

    You have? Good. Me too. And you’re in the right place.

    This article will explain how to both execute functions and remove inputs by a press (or hold) of a button.

    First, I will explain how to achieve this in VanillaJS. Then, create a Vue directive for it.

    Buckle up. I’m about to blow your mind.

    Theory

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

    To replicate this in code, we need to listen to when the mouse “click” button is pressed, start a timer for however long we want the user to hold down the button before executing the function, and execute the function after the time set has passed.

    Pretty straightforward! However, we need to know when the user is holding down that button.

    How-to

    When a user clicks a button, two other events gets fired before the click event: mousedown and mouseup.

     

    The mousedown event gets called when the user presses the mouse button, while the mouseup event gets called when the user releases that button.

    All we need to do is:

    1. Start a timer once the mousedown event occurs
    2. Clear that timer and don’t execute the function once the mouseup event gets fired before the 2secs mark, i.e., a full click event

    As long as the timer doesn’t get cleared before it gets to that time we’ve set — i.e., the mouseup event doesn’t get fired — we can say that user hasn’t released the button. Therefore, it’s considered a long press and we can then proceed to execute said function.

    Practical

    Let’s dive into the code and get this done.

    Firstly, we have to define three things, namely:

    1. A variable to store the timer
    2. A start function to start the timer
    3. A cancel function to cancel the timer

    Variable

    This variable basically holds the value of the setTimeout so we can cancel this when a mouseup event occurs.

    We are setting the variable to null just so we can check the variable to know if there’s an active timer currently on before going ahead to cancel it.

    Start function

    This function consists of a setTimeout which, basically, is a method in Javascript that allows us to execute a function after a particular duration stated in the function.

    Remember, in the process of creating a click event, two events gets fired. But what we need to start the timer is the mousedown event. Therefore, we do not need to start the timer if it’s a click event.

    Cancel function

    This function basically does what the name says, to cancel the setTimeout that was created when the start function got called.

    To cancel the setTimeout, we would be using the clearTimeout method in JavaScript, which basically clears a timer set with the setTimeout() method.

    Before using the clearTimeout we first need to check if the pressTimer variable is set to null. If it’s not set to null that means there’s an active timer. So, we need to clear the timer and, you guessed it, set the pressTimer variable to null.

    This function would be called once the mouseup event is fired.

    Setting triggers

    What’s left is to add event listeners to the button you want to add the long press effect on.

    addEventListener("mousedown", start);
    addEventListener("click", cancel);

    Wrapping it all in a Vue directive

    When creating a Vue directive, Vue allows us to define a directive globally or locally to a component, but in this article we would be going the global route.

    Let’s build the directive that accomplishes this.

    Firstly we have to declare the name of the custom directive.

    This basically registers a global custom directive named v-longpress.

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

    Vue.directive('longpress', {
      bind: function (el, binding, vNode) {
        
      }
    }

    Next, we make add our long-press JavaScript code in the bind function.

    Vue.directive('longpress', {
        bind: function (el, binding, vNode) {
    
            // Define variable
            let pressTimer = null
    
            // Define funtion handlers
            // Create timeout ( run function after 1s )
            let start = (e) => {
    
                if (e.type === 'click' && e.button !== 0) {
                    return;
                }
    
                if (pressTimer === null) {
                    pressTimer = setTimeout(() => {
                        // Execute something !!!
                    }, 1000)
                }
            }
    
            // Cancel Timeout
            let cancel = (e) => {
                // Check if timer has a value or not
                if (pressTimer !== null) {
                    clearTimeout(pressTimer)
                    pressTimer = null
                }
            }
    
            // Add Event listeners
            el.addEventListener("mousedown", start);
            // Cancel timeouts if this events happen
            el.addEventListener("click", cancel);
            el.addEventListener("mouseout", cancel);
        }
    })

    Next, we need to add a function that would run the method that will be passed to the longpress directive.

    Vue.directive('longpress', {
        bind: function (el, binding, vNode) {
    
            // Define variable
            let pressTimer = null
    
            // Define funtion handlers
            // Create timeout ( run function after 1s )
            let start = (e) => {
    
                if (e.type === 'click' && e.button !== 0) {
                    return;
                }
    
                if (pressTimer === null) {
                    pressTimer = setTimeout(() => {
                        // Execute function
                        handler()
                    }, 1000)
                }
            }
    
            // Cancel Timeout
            let cancel = (e) => {
                // Check if timer has a value or not
                if (pressTimer !== null) {
                    clearTimeout(pressTimer)
                    pressTimer = null
                }
            }
            // Run Function
            const handler = (e) => {
                // Execute method that is passed to the directive
                binding.value(e)
            }
    
            // Add Event listeners
            el.addEventListener("mousedown", start);
    
            // Cancel timeouts if this events happen
            el.addEventListener("click", cancel);
            el.addEventListener("mouseout", cancel);
            
        }
    })

    Now we can use the directive in our Vue application which will work fine until a user adds a value that isn’t a function in the value of the directive. So we have to prevent this by warning the user once this happens.

    To warn the user, we add the following to the bind function:

    // Make sure expression provided is a function
    if (typeof binding.value !== 'function') {
      // Fetch name of component
      const compName = vNode.context.name
      // pass warning to 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)
    }

    Lastly, it would be great for this directive to also work on touch devices. So we add event listeners for touchstarttouchendtouchcancel.

    Putting everything together:

    Vue.directive('longpress', {
        bind: function (el, binding, vNode) {
            // Make sure expression provided is a function
            if (typeof binding.value !== 'function') {
                // Fetch name of component
                const compName = vNode.context.name
                // pass warning to 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)
            }
    
            // Define variable
            let pressTimer = null
    
            // Define funtion handlers
            // Create timeout ( run function after 1s )
            let start = (e) => {
    
                if (e.type === 'click' && e.button !== 0) {
                    return;
                }
    
                if (pressTimer === null) {
                    pressTimer = setTimeout(() => {
                        // Run function
                        handler()
                    }, 1000)
                }
            }
    
            // Cancel Timeout
            let cancel = (e) => {
                // Check if timer has a value or not
                if (pressTimer !== null) {
                    clearTimeout(pressTimer)
                    pressTimer = null
                }
            }
            // Run Function
            const handler = (e) => {
                binding.value(e)
            }
    
            // Add Event listeners
            el.addEventListener("mousedown", start);
            el.addEventListener("touchstart", start);
            // Cancel timeouts if this events happen
            el.addEventListener("click", cancel);
            el.addEventListener("mouseout", cancel);
            el.addEventListener("touchend", cancel);
            el.addEventListener("touchcancel", cancel);
        }
    })

    Now to reference in our Vue component:

    <template>
        <div>
            <button v-longpress="incrementPlusTen" @click="incrementPlusOne">{{value}}</button>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                value: 10
            }
        },
        methods: {
            // Increment value plus one
            incrementPlusOne() {
                this.value++
            },
            // increment value plus 10
            incrementPlusTen() {
                this.value += 10
            }
        }
    }
    </script>

    Conclusion

    If you would love to know more about custom directives, the hook functions that are available, the arguments you can pass into this hook functions, and function shorthands, the great guys @vuejs have done a great job of explaining it here.

    Cheers !!!

  • 相关阅读:
    Javascript--普通函数调用-涨工资计算函数
    Javascript--运算符判断成绩运算
    Javascript-闰年javascript的判断
    Javascript-逻辑判断或(&&)练习
    Javascript-短路 与(&&)
    UVALive6434_Number Assignment
    HDU4811_Ball
    HDU4810_Wall Painting
    HDU4803_Poor Warehouse Keeper
    HDU4802_GPA
  • 原文地址:https://www.cnblogs.com/144823836yj/p/14896950.html
Copyright © 2011-2022 走看看