背景
项目中,常用到一些utils,像深拷贝、数组去重、函数的节流防抖等。引入lodash,基本就覆盖绝大多数场景了。
但也一种新思路,就是vue自定义指令;
这里记录一下,自定义指令节流和防抖。
官网对自定义指令介绍
除了核心功能默认内置的指令 (
v-model和v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。举个聚焦输入框的例子,如下:当页面加载时,该元素将获得焦点 (注意:
autofocus在移动版 Safari 上不工作)。事实上,只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在让我们用指令来实现这个功能:// 注册一个全局自定义指令 `v-focus` Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } })
官网链接地址 cn.vuejs.org/v2/guide/cu…
代码实现
防抖
事件触发后,开始倒计时,倒计时结束函数执行;如果倒计时期间再次触发 则重新开始倒计时
用于:按钮的防重提交、输入框的延时保存、输入框输入查询、机顶盒输入频道切换等场景
新建src/directive/debounce.js
import Vue from 'vue'
/**
* 防抖 就是指触发事件后在 特定间隔内 函数只能执行一次,如果在时间间隔内又触发了事件,则会重新计算函数执行时间
*三个入参 响应函数名 时长 绑定事件名
* v-debounce="['addF',1000,'click']"
*/
Vue.directive('debounce', {
inserted: function (el, bindingObj) {
let timer //定义计时器对象
let [fn, time = 300, attr = 'click'] = bindingObj.value //解构取值 时间默认300毫秒 绑定事件默认click
el.addEventListener(attr, () => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => fn(), time)
})
}
})
main.js 引入一下
import "@/directive/debounce.js"
test.vue
<van-button type="info" v-debounce="[addF,1000]">点击测试debounce</van-button>
节流
事件持续触发,特定时间内只执行一次。让一个函数不要执行得太频繁,无论事件触发多少次,也就回调一次
用于鼠标不断点击触发mousedown(单位时间内只触发一次)、监听滚动事件,滚动条位置懒加载、机顶盒,多次按频道或音量加减键
新建throttle.js
import Vue from 'vue'
/**
* 节流 持续触发某个事件 特定时间间隔内只执行一次
*三个入参 响应函数名 时长 绑定事件名
* v-throttle="['addF',1000,'click']"
*/
Vue.directive('throttle', {
inserted: function (el, bindingObj) {
let flag, timer
let [fn, time = 300, attr = 'click'] = bindingObj.value //解构取值 时间默认300毫秒 绑定事件默认click
el.addEventListener(attr, () => {
if (flag) {
//还没清除又触发了 就中断执行return false 重新倒计时
console.log('enter flag')
clearTimeout(timer)
timer = setTimeout(() => fn(), time)
return false
}
fn()
flag = setTimeout(() => flag = null, time) //触发后 规定时间间隔 将flag清除
})
}
})
main.js 引入一下
import "@/directive/throttle.js"
test.vue
<van-button type="info" v-throttle="[delF,1000]">点击测试throttle</van-button>
首页点击节流防抖进入调试页。