使用去抖将参数传递给方法的函数-Vue

时间:2018-08-26 05:24:47

标签: vue.js vuejs2 debounce

模板:

<input @keyup="fetchData(0)" v-model="name">

方法:

  methods: {
    fetchData: _.debounce(function (value) {
      console.log('Argument is: ' + value)
      axios.get(globalConfig.ORDERS_URL, {
        params: {
          limit: this.perPage,
          offset: (this.currentPage - 1) * this.perPage,
          name: this.name,
          phone: this.phone,
          from_date: this.dateOne,
          to_date: this.dateTwo
        }
      })
        .then((resp) => {
          this.req = resp.data
          // console.log(resp)
        })
        .catch((err) => {
          console.log(err)
        })
    }, 500)
  }

使用参数0-fetchData调用fetchData(0),但是由于我使用的是_.debounce,它不会通过。控制台日志显示“未定义”

如何正确传递参数?

3 个答案:

答案 0 :(得分:2)

尚未检查以下代码,但我想解释更多有关反跳以及Vue中“ v-on”或“ @”事件如何工作的信息。

在您的<input>标签上,您可以使用<input @input="fetchData" v-model="name">,如@dziraf所述,并为多余的变量做很多额外的工作。或...

要发送参数,您只需简单地先明确包含“ EVENT”变量(在Vue.js事件中,其名称为$ event),然后再选择添加:

<input 
  @input="fetchData($event, 'Custom Values', customVariables)"
  v-model="name"
>

现在,您可以访问发送到“您的函数”或“去抖动的函数”(这只是您发送的任何函数的包装版本)的所有变量:

methods: {
  fetchData: 
    _.debounce( 
      (e, customVariable1=undefined, customVariable2=undefined) => {
        console.log('Input argument is: ' + e.target.value);
      }, 500),
...

提示:2个customVariable中的“ = undefined”用于使它们成为可选。

警告:请注意,如果您将在单个页面上实现此组件的多个实例,则由于某些初始过程中存在封装问题,因此不建议在methods:中使用去抖动功能Vue生命周期挂钩。另外,我认为在进行其他用户交互时,如果需要,您将无法调用.cancel()方法,并在延迟结束之前停止该功能。

建议在created()生命周期中将函数保存到变量,而不是method:

created() {
  this.fetchData = _.debounce( 
    (e, customVariable1=undefined, customVariable2=undefined) => {
      console.log('Input argument is: ' + e.target.value);
    }, 500);
}

现在,您可以调用.cancel()方法来正确地进行垃圾收集:

beforeDestroy() {
  this.fetchData.cancel();
}

或者,具有“取消”按钮,或通过其他UI元素进行调用:

<button @click="fetchData.cancel();">Cancel the Request</button>

您可以尝试以下代码以查看封装中的细微差别:

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

<div id="app">
  <div>Using debounce as a data() variable declared in created():</div>
  <create-change ref="counter1"></create-change>
  <create-change ref="counter2"></create-change>
  <create-change ref="counter3"></create-change>
  <create-change ref="counter4"></create-change>
  <br />
  <br />
  <div>Using debounce as a Method:</div>
  <method-change ref="counter5"></method-change>
  <method-change ref="counter6"></method-change>
  <method-change ref="counter7"></method-change>
  <method-change ref="counter8"></method-change>
</div>

JS

Vue.component('create-change', {

  template:
    `
      <button @click="changeContent($event,'any custom value')">
        Click to change my value: {{ i }}
      </button>
    `,

  data: function(){
    return { i: 0 };
  },

  created() {
   this.changeContent = _.debounce(function(e, val=0){
      if (val) { this.i = val } // or reference a method here
    }, 1000)
  },

});

Vue.component('method-change', {

  template: 
    `
      <button @click="changeContent($event,'any custom value')">
        Click to change my value: {{ i }}
      </button>
    `,

  data: function(){
    return { i: 0 };
  },

  methods: {

    // WARNING: Can have encapsulation issues
   changeContent: _.debounce(function(e, val=0){
      if (val) { this.i = val }
    }, 1000),

  },

});


new Vue({
  el: '#app',
  mounted () {
    this.$refs.counter1.changeContent(null,1);
    this.$refs.counter2.changeContent(null,2);
    this.$refs.counter3.changeContent(null,3);
    this.$refs.counter4.changeContent(null,4);
    this.$refs.counter5.changeContent(null,5);
    this.$refs.counter6.changeContent(null,6);
    this.$refs.counter7.changeContent(null,7);
    this.$refs.counter8.changeContent(null,8);
  }
});

CSS

#app {
  margin: 20px;
  font-size: 20px;
  font-family: Arial, sans-serif;  
}

答案 1 :(得分:0)

安装debounce软件包。

将其导入您的组件中

import debounce from 'debounce'

通过从0中删除fetchData来更新模板:

<input @input="fetchData" v-model="name">

我将事件更改为@input,但它也可以与@keyup一起使用。

然后将您的功能更改为:

fetchData: debounce(e => {
  console.log('Input argument is: ' + e.target.value);
}, 500)

https://codesandbox.io/s/8x6rj4lnzl(App.vue)

答案 2 :(得分:0)

我也一直在寻找解决方案,总的来说,这是一个有效的版本,希望它可以帮助您节省一分钟的时间:)

// Lodash or any custom function debounce
import _ from 'lodash';

const template = `
   <input v-model="textInput">
`;

export default {
    template: template,
    data: () => {
        return {
            textInput: null
        }
    },
    created: function() {
        let vue = this;

        vue.debouncedApiPatch = _.debounce(vue.apiPatch, 500);

        vue.$watch('textInput', function (val) {
            vue.debouncedApiPatch('textInput', val);
        })
    },
    methods: {
        apiPatch: function (prop, val) {
            console.log(prop, val);
            // api async patch...
        }
    }
}