以vue元件或者外掛的形式,實現throttle或者debounce

虛光發表於2018-12-18

需求

  • 在業務中,會碰到許多點選請求的情況,在請求前改變一個lock變數(在lock變回來之前,點選無效),在請求回撥中再改變lock.以確保在,請求回來之前,不會重複請求。或者類似的點選節流業務

實現方式

指令

 <div v-for="a in 3" :key="a" v-demo:getData="a">指令</div>
 //getData是函式名,a是傳入的引數
    directives: {
    demo: {
      bind(el: Element, binding: any, vnode: VNode) {
        const that: any = vnode.context
        // console.log(binding, vnode)
        // console.log(binding.arg, binding.value)
        if (!that[binding.arg].isBind){  // 打上標記,如果已經轉換了,就不轉了
          that[binding.arg] = deb(that[binding.arg])
          that[binding.arg].isBind = true
        }
        el.addEventListener('click', function T(event: Event): void{
          that[binding.arg](binding.value)
        })
      },
    },
  },
複製程式碼

元件

  • 子元件
<template>
  <div>
    <div @click="senClick">
      <slot></slot>
    </div>
  </div>
</template>
<script lang="ts">
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
@Component({})
export default class Child extends Vue {
  @Prop({ type: Number, default: 500 }) public timeOut!: number; // 時間
  @Prop({ type: String, default: 'throttle' }) public type!: string; // 型別
  @Prop() public params!: any; // 傳入引數
  public message: string = 'Hello';
  public throttleLock: boolean = false;
  public debounceLock: number = 0;
  public time: any;
  public senClick(): void {
    console.log(this.timeOut, this.type, this.params);
    if (this.type === 'throttle') {
      if (this.throttleLock) {
        return;
      }
      this.throttleLock = true;
      setTimeout(() => {
        this.throttleLock = false;
      }, this.timeOut);
      this.$emit('myClick', this.params);
    } else if (this.type === 'debounce') {
      if (this.debounceLock) {
        clearTimeout(this.debounceLock);
      }
      this.debounceLock = setTimeout(() => {
        this.$emit('myClick', this.params);
      }, this.timeOut);
    } else {
      this.$emit('myClick', this.params);
    }
  }
}
</script>

<style  scoped lang='stylus'>
div {
  width: 100%;
  height: 100%;
}
</style>

複製程式碼

父元件

<template>
  <div class="home">
      <throttle-and-debounce @myClick="getData" :time="500" type="throttle" params="123">
        <div>我是元件內容</div>
      </throttle-and-debounce>
  </div>
</template>
import { Component, Vue } from 'vue-property-decorator';
import throttleAndDebounce from '@/components/throttleAndDebounce.vue'; 
@Component({
  components: {
    throttleAndDebounce,
  },
})
export default class home extends Vue {
public getData(e: any){
      console.log('非同步資料', e)
    }
}

</script>
複製程式碼

plugin

  • 函式
function deb(fn: function){
  let lock: number
  return (e) => {
    if (lock){
      clearTimeout(lock)
    }
    console.log('建立閉包延遲執行')
    lock = setTimeout(() => {
      fn(e)
    }, 1500)
  }
}
export {deb}
複製程式碼

元件內使用

<template>
  <div class="home">
    <div @click="func(123)">function</div>
  </div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import {deb} from '@/assets'
@Component({
  components: {
    throttleAndDebounce,
  },
})
export default class home extends Vue {
     public beforeCreate(){
         this.func = deb((e: {a: number}) => {
          console.log('this', e)
        })
      }
}
</script>
複製程式碼

相關文章