Vue event util

The util of Vue event. Provides extended functions such as throttling, debounce, delay.

Version: 0.0.2 Updated: 09/29/2018

By: laden666666 License: MIT

Downloads Last 30 Days: 28

Install

npm i vue-event-util
yarn add vue-event-util

CDNs

bundle.run: https://bundle.run/vue-event-util

jsDelivr: https://cdn.jsdelivr.net/npm/vue-event-util

unpkg: https://unpkg.com/vue-event-util

vue-event-util

Version Downloads License

vue-event-util,是一个Vue事件的扩展插件,为Vue的事件提供了如函数节流(throttle)函数防抖(debounce)函数延时(delay) 等功能。vue-event-utillodash 的很多处理函数的工具函数加入到插件中,大家可用使用vue-event-util提供的便携方法将其应用到Vue的事件中。

源码

github码云

功能

  • 0.对Vue的事件响应函数提供函数防抖(throttle)函数节流(debounce)延时执行(delay) 等函数处理功能
  • 1.对某控件所有实例共享的函数进行函数防抖和函数节流
  • 2.对某控件各个实例的函数进行函数防抖和函数节流
  • 3.对列表渲染的控件绑定的函数进行函数防抖和函数节流
  • 4.实现防止按钮连击
  • 5.实现降低事件响应频率
  • 6.实现延时事件响应

兼容性

AndroidFirefoxChromeIEiPhoneEdgeSafari
>=4.4>=9

例子

防止按钮连击:docs/ButtonSafe.html 源码

事件降频触发:docs/FrequencyReduction.html 源码

事件延时触发:docs/Delay.html源码

插件解决的问题

当我们对函数进行柯里化函数节流函数防抖处理的时候,往往需要将原有函数以入参传入,并以返回函数的形式返回处理后的函数。如lodash库对函数防抖的实现:

fn = _.throttle(fn, 1000)

但是这个处理对于Vue的template语法中的事件响应函数来说,实现起来很麻烦,我们以做函数防抖为例,看看我们以往在Vue中是如何实现上述操作的。Vue的事件绑定有两种方法:方法名绑定内联处理器内联处理器允许我们提供一个表达式处理事件,但表达式没有记忆功能,因此无法实现如函数节流函数防抖这样的功能。

<template>
    <button @clikc="_.throttle(fn, 1000)()">函数节流</button>
</template>

每一次点击都会执行一次_.throttle方法,所以上述代码是无法实现对事件的函数节流处理的。

另一种方法是先将函数进行处理,再通过方法名绑定或者内联处理器的方式绑定到Vue上面。

<template>
    <button @clikc="fn">函数节流</button>
</template>
<script>
    export deflaut {
        methods: {
            fn: _.throttle(function(){
                ...
            }, 1000)
        },
    }
</script>

这样写也存在一个问题,就是所有控件公用一个节流函数,当多个控件需要单独做函数节流的话就没有办法了。而且对于列表渲染,如果列表的每一个控件都要单独做函数节流处理,这样就更麻烦了。

有时候我们甚至会借助watch来实现函数节流的功能。如:

<template>
    <button @clikc="fn">函数节流</button>
</template>
<script>
    export deflaut {
        created() {
            this.$watch('clickTime', _.throttle(() => {
                ...
            }, 200))
        }
        data: {
            clickTime: 0,
        }
        methods: {
            fn: function(){
                this.clickTime++
            }
        },
    }
</script>

方法是死的人是活的,我们肯定能找到更优雅的方式来做函数节流或者其他类似的事情。vue-event-util就是为了解决这个事情而生的。

安装

npm install vue-event-util

然后在js中执行

import vueEventUtil from 'vue-event-util'
import Vue from 'vue'

Vue.use(vueEventUtil)

在浏览器环境中,直接将vue-event-util.js文件引入即可。

<script src="vue-event-util.js"></script>
<script>
    Vue.use(vueEventUtil)
</script>

使用

vue-event-util提供了lodash的delaythrottledebounce等方法

  • delay: 延迟 wait 毫秒后调用 func
  • debounce: 创建一个 debounced(防抖动)函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用 func 方法。
  • throttle: 创建一个节流函数,在 wait 秒内最多执行 func 一次的函数

三种函数具体用法可以参考lodash

delay

延迟 wait 毫秒后调用 callback

参数
参数名 参数类型 参数说明
callback Function 延迟执行的函数
wait number 延迟的时间,单位毫秒
返回值
参数类型 参数说明
Function 处理后的函数

debounce

创建一个 debounce(防抖动)函数,该函数会从上一次被调用后,延迟 wait 毫秒后调用 callback 方法。

参数
参数名 参数类型 参数说明
callback Function 需要做防抖函数
wait number 延迟的时间,单位毫秒
options object 选项对象
options.leading boolean 指定调用在延迟开始前,默认false
options.maxWait number 设置 func 允许被延迟的最大值
options.trailing boolean 指定调用在延迟结束后,默认true
返回值
参数类型 参数说明
Function 处理后的函数

throttle

创建一个节流函数,在 wait 秒内最多执行 callback 一次的函数

参数
参数名 参数类型 参数说明
callback Function 需要做节流函数
wait number 节流时间,单位毫秒
options object 选项对象
options.leading boolean 指定调用在节流开始前,默认true
options.trailing boolean 指定调用在节流结束后,默认false(与lodash默认配置不同,主要是因为事件处理更常用trailing为false的情况,如防止按钮连击)
返回值
参数类型 参数说明
Function 处理后的函数

这些方法可以通过3种方式对Vue控件的函数进行处理:

  • 1.全局函数
  • 2.控件实例函数
  • 3.列表渲染函数

全局函数

vue-event-util提供某控件所有实例共享的函数进行上述函数处理,这种使用方法,相当于作用于控件原型上的函数,一旦方法进行了处理后,控件的每一个实例会共享处理后的方法。通过vue-event-util上提供的这些全局处理方法,具体用法如下:

import eventUtil from 'vue-event-util'
export deflaut {
    methods: {
        delay: eventUtil.delay(function(argument){
            ...
        }, 100),
        throttle: eventUtil.throttle(function(argument){
            ...
        }, 100),
        debounce: eventUtil.debounce(function(argument){
            ...
        }, 100),
    }
}

控件实例函数

vue-event-util在Vue实例的原型上提供了上述函数处理,使用原型上的方法去处理函数,处理后的结果是控件实例独享的,针对Vue事件绑定函数的方法不同,vue-event-util提供两种不同的方法:

可以在方法里面使用$xxx函数里调用的方式,方法名绑定,如

<template>
    <div class="test">
        <p>方法里面调用vue-event-util处理函数</P>
        <button @click="delay(count)" >delay2</button>
        <button @click="throttle(count)" >throttle2</button>
        <button @click="debounce(count)" >debounce2</button>
        <p>内联处理器里调用vue-event-util处理函数</P>
        <button @click="$delay(method, 1000)('delay')" >delay</button>
        <button @click="$throttle(method, 1000)('throttle')" >throttle</button>
        <button @click="$debounce(method, 1000)('debounce')" >debounce</button>
    </div>
</template>
<script>
export default {
    methods: {
        method(parameter){
            console.log(parameter)
        },
        //方法里面调用vue-event-util的delay函数
        delay(parameter){
            this.$delay((parameter)=>{
                this.method(parameter)
            }, 1000)(parameter)
        },
        //方法里面调用vue-event-util的throttle函数
        throttle(parameter){
            this.$throttle((parameter)=>{
                this.method(parameter)
            }, 1000)(parameter)
        },
        //方法里面调用vue-event-util的debounce函数
        debounce(parameter){
            this.$debounce((parameter)=>{
                this.method(parameter)
            }, 1000)(parameter)
        },
    },
}
</script>

可以在方法里面调用vue-event-util函数:

export default {
    methods: {
        method(parameter){
            console.log(parameter)
        },
        throttle(parameter){
            //将函数真正的处理逻传入vue-event-util的$throttle函数里,实现对函数节流的效果
            this.$throttle((parameter)=>{
                this.method(parameter)
            }, 1000)(parameter)
        },
    }
}
</script>

也可以在内联处理器里调用vue-event-util处理函数:

<template>
    <div class="test">
        <button @click="$throttle(method, 1000)('throttle')" >throttle</button>
    </div>
</template>
<script>
export default {
    methods: {
        method(parameter){
            console.log(parameter)
        },
    },
}
</script>

列表渲染函数

当出现列表循环的时候,如果希望每一个循环出的元素拥有自己的事件处理函数,可以给每个元素提供一个key,使得各个元素绑定的事件互不干扰,例:

<template>
    <div class="test">
        <p>方法里面调用vue-event-util处理函数</P>
        <button v-for="key in 5" :key="key" @click="delay(key, count)" >delay2</button>
        <button v-for="key in 5" :key="key" @click="throttle(key, count)" >throttle2</button>
        <button v-for="key in 5" :key="key" @click="debounce(key, count)" >debounce2</button>
        <p>内联处理器里调用vue-event-util处理函数</P>
        <button v-for="key in 5" :key="key" @click="$delay(key, method, 1000)('delay')" >delay</button>
        <button v-for="key in 5" :key="key" @click="$throttle(key, method, 1000)('throttle')" >throttle</button>
        <button v-for="key in 5" :key="key" @click="$debounce(key, method, 1000)('debounce')" >debounce</button>
    </div>
</template>
<script>
export default {
    methods: {
        method(parameter){
            console.log(parameter)
        },
        //方法里面调用vue-event-util的delay函数
        delay(key, parameter){
            this.$delay(key, (parameter)=>{
                this.method(parameter)
            }, 1000)(parameter)
        },
        //方法里面调用vue-event-util的throttle函数
        throttle(key, parameter){
            this.$throttle(key, (parameter)=>{
                this.method(parameter)
            }, 1000)(parameter)
        },
        //方法里面调用vue-event-util的debounce函数
        debounce(key, parameter){
            this.$debounce(key, (parameter)=>{
                this.method(parameter)
            }, 1000)(parameter)
        },
    },
}
</script>

原理

vue-event-util是如何存对Vue绑定的函数实现记忆呢?

将每一个需要处理的函数toString,然后和其他参数(key,wait,option)一起做一个hash,最后用这个hash值做key将处理后的函数缓存起来。这是一个享元模式,如果hash已经存在就从缓存里面取,如果不存在就对函数进行处理,再缓存。因为如果一个函数的key、wait、option都相同,那这个函数的hash值也相同,所以就可以缓存这个函数了。

Categories: Vue js