Vue组件实现函数防抖
最近在掘金看到兩篇非常不錯的文章:
- 以vue組件或者插件的形式,實現throttle或者debounce
- 奇技淫巧 - Vue Mixins 高級組件 與 Vue HOC 高階組件 實踐
這兩篇文章中作者都分享了關于把函數防抖/函數節流包裝成通用組件的經驗。
在這里我就不介紹函數防抖/函數節流的概念了,將這樣的功能封裝是組件真的是非常實用。
通過HOC(高階組件)的方式進行封裝的思路我也很喜歡,這里也想分享一個類似的封裝方法
抽象組件
這里我使用了abstract: true來創建一個抽象組件。
我們常用的transition和keep-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組件會接受time和events(用逗號分隔)的兩個參數。
在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组件实现函数防抖的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从各类信用利差走势看风险偏好
- 下一篇: 文远知行A轮再获数千万美元融资 商汤科技