最近在掘金看到两篇非常不错的文章:

  • 以vue组件或者插件的形式,实现throttle或者debounce
  • 奇技淫巧 - Vue Mixins 高级组件 与 Vue HOC 高阶组件 实践

这两篇文章中作者都分享了关于把函数防抖/函数节流包装成通用组件的经验。

在这里我就不介绍函数防抖/函数节流的概念了,将这样的功能封装是组件真的是非常实用。

通过HOC(高阶组件)的方式进行封装的思路我也很喜欢,这里也想分享一个类似的封装方法

抽象组件

这里我使用了abstract: true来创建一个抽象组件。

我们常用的transitionkeep-alive就是一个抽象组件。抽象组件是无状态的,同样也是“不存在的”,它自己并不会被渲染为实际的DOM,而是直接返回以及操作它的子元素。

例如对于模板(Debounce是一个抽象组件):

<Debounce><button>123</button>
</Debounce>
复制代码复制代码

会被渲染成:

<button>123</button>
复制代码复制代码

实现

这里直接贴出组件代码:

const debounce = (func, time, ctx) => {let timerconst rtn = (...params) => {clearTimeout(timer)timer = setTimeout(() => {func.apply(ctx, params)}, time)}return rtn
}Vue.component('Debounce', {abstract: true,props: ['time', 'events'],created () {this.eventKeys = this.events.split(',')this.originMap = {}this.debouncedMap = {}},render() {const vnode = this.$slots.default[0]this.eventKeys.forEach((key) => {const target = vnode.data.on[key]if (target === this.originMap[key] && this.debouncedMap[key]) {vnode.data.on[key] = this.debouncedMap[key]} else if (target) {this.originMap[key] = targetthis.debouncedMap[key] = debounce(target, this.time, vnode)vnode.data.on[key] = this.debouncedMap[key]}})return vnode},
})
复制代码复制代码

Debounce组件会接受timeevents(用逗号分隔)的两个参数。

render函数中,Debounce组件修改了子VNode的事件,再将其返回回去。

使用

然后我们来使用一下:

<div id="app"><Debounce :time="1000" events="click"><button @click="onClick($event, 1)">click+1 {{val}}</button></Debounce><Debounce :time="1000" events="click"><button @click="onClick($event, 2)">click+2 {{val}}</button></Debounce><Debounce :time="1000" events="mouseup"><button @mouseup="onAdd">click+3 {{val}}</button></Debounce><Debounce :time="1000" events="click"><button @mouseup="onAdd">click+3 {{val}}</button></Debounce>
</div>
复制代码复制代码
const app = new Vue({el: '#app',data () {return {val: 0,}},methods: {onClick ($ev, val) {this.val += val},onAdd () {this.val += 3}}
})
复制代码复制代码

使用指令

使用自定义指令也是一种思路,不过指令的bind发生在created的回调中,也就是晚于事件的初始化的,这样的话就不能通过修改vnode.data.on来改变绑定的事件回调,只能自己来绑定事件了:

Vue.directive('debounce', {bind (el, { value }, vnode) {const [target, time] = valueconst debounced = debounce(target, time, vnode)el.addEventListener('click', debounced)el._debounced = debounced},destroy (el) {el.removeEventListener('click', el._debounced)}
})
复制代码复制代码

这里要注意的一点是,指令binding.value的求值过程和事件绑定是不同的,并不支持onClick($event, 2)的写法,因此如果这样的绑定就只能再包一层了:

<button v-debounce="[($ev) => { onClick($ev, 4) }, 500]">click+4 {{val}}</button>
复制代码复制代码

小结

使用抽象组件的好处是提高了组件的通用性,不会因为组件的使用而污染DOM(添加并不想要的div标签等)、可以包裹任意的单一子元素,当然也有缺点,比如使用时要注意子元素只能包含一个根,使用起来也比较啰嗦(参考文章中ButtonHoc在使用时更简洁一些,但相应的是只能作为Button渲染)。

Vue组件实现函数防抖相关推荐

  1. vue 组件之间函数传递_组件之间相互传递参数

    ### RT:A,B两个页面传递参数 常用方法:`@click`的方式调用`$touter.push()`或者``的方式. `push`方法:接收三个参数`name`,`params`,`query` ...

  2. java socket中属性详解_前端开发:关于Vue组件中的data属性值是函数而不是对象的详解...

    最近在搞关于前端开发的基础知识归纳,发现了不少经典知识点,那么本篇博文就来分享一个经典的知识点:Vue组件中的data属性值为什么是函数而不是对象.首先来了解一下Vue组件的使用理念:在Vue组件使用 ...

  3. vue iframe 中写script_vue: 单文件组件 render函数

    使用vue-cli创建的vue项目,如何在这种项目中使用组建? 首先创建项目.启动项目 我们再来了解一下目录结构,src文件夹是写逻辑代码的地方,public是最终渲染到浏览器的地方. 在public ...

  4. Vue 组件 data为什么是函数

    在创建或注册模板的时候,传入一个data属性作为用来绑定的数据.但是在组件中,data必须是一个函数,而不能直接把一个对象赋值给它. Vue.component('my-component', {te ...

  5. 为什呢vue组件中的data必须是函数?

    类比引用数据类型 Object是引用数据类型,如果不用function 返回,每个组件的data 都是内存的同一个地址,一个数据改变了其他也改变了; 关于JS中的数据类型:https://blog.c ...

  6. vue组件中的data为什么是一个函数

    一.总结 1.vue中组件是用来复用的,为了防止data复用,将其定义为函数. 2.vue组件中的data数据都应该是相互隔离,互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处 ...

  7. 为什么Vue组件里面data必须是个函数

    Vue组件里面data必须是个函数 **首页我们先了解一个原形和原型链,每个js对象和js方法都有一个原形,js对象的是隐式原形 proto,而方法中的是显示原形prototype,下面举个例子: e ...

  8. Vue 组件中的data为什么是一个函数?

    1.前言 在学习Vue的时候,发现组件中的data 是函数返回的形式,而挂载的实例中的data一般都是简单的对象格式,带着问题查了查文档,下面给出例子和解释. 2.正文 这里有一个 Vue 组件的示例 ...

  9. vue自定义指令之防抖函数

    在项目中会遭遇到用户连续点击多次按钮的情况, 这个时候就需要使用防抖函数,在一定时间内只触发一次函数执行. 实现 在 Vue 项目中,在 src > utils 目录下新建 Debounce.j ...

最新文章

  1. 无法解决 equal to 操作中 SQL_Latin1_General_CP1_CI_AS 和 Chinese_PRC_CI_AS 之间的排序规则冲突。...
  2. jsp注册里密码强弱怎么弄_jsp+servlet实战酷炫博客+聊天系统
  3. centos7 安装java 8_CentOS 7.8下安装完美安装配置Rosetta
  4. axis2 java.net.url_axis2调用.net写的webservice接口实现,指定参数名
  5. 单位阶跃信号是周期信号吗_直流散热风扇的信号你知道如何控制吗?
  6. 鸿蒙有什么好处,鸿蒙系统有什么好处-鸿蒙系统有什么用-鸿蒙系统有什么区别...
  7. 转:nginx allow 多个ip ipv4的网段表示方法解析
  8. 万科企业宗旨、愿景与核心价值观
  9. python 005 __ 小斌文档 | 函数的定义和调用
  10. Windows Server 2008 R2 安装及配置
  11. 一日一签免费算卦_一日一签app免费算卦
  12. Visual Studio 2015/2017 与ASP.NET CORE 联合创建具有SPA模式的Angular2模板
  13. ASR6601牛羊定位器芯片GPS国内首颗支持LoRa的LPWAN SoC
  14. Vue2积分商城PC端项目(一)
  15. PHP 函数、类声明和调用
  16. C++_输入一个字符串,并逆序输出
  17. 苹果笔记本恢复服务器上的安装信息已被破坏,Mac电脑如何恢复删除或已损坏无法打开的Word文件?...
  18. 边缘AI+视频监控,如何助力企业安全生产监管智能化升级?
  19. 为什么工程师出身的 CEO 越来越“香”?
  20. Python(py3fdfs)上传到fastdfs配置store_serv.ip_addr问题

热门文章

  1. python代理爬取存入csv文件
  2. .Net微信开发之通过UnionID机制,解决用户在不同公众号,或在公众号、移动应用之间帐号统一问题...
  3. CommonJs模块规范
  4. 【转】ora-00031:session marked for kill处理oracle中杀不掉的锁
  5. 数学图形(2.19) 利萨茹3D曲线
  6. Java内存溢出分析
  7. Windows核心编程 第26章 窗口消 息
  8. Windows核心编程 第十八章 堆栈
  9. POJ1151基本的扫描线求面积
  10. 【Groovy】MOP 元对象协议与元编程 ( 方法注入 | 使用 MetaClass 进行方法注入普通方法 )