开发者问题收集

如何使用 VueJS 消除 AJAX 调用的抖动?

2016-04-10
6463

我试图对 AJAX 调用进行去抖动,以便只发送一次,但不幸的是,它告诉我传递给它的不是一个函数。这是我的代码:

getItems: function(page){
  this.page = page;
  console.log(typeof(this.getBackendItems));
  _.debounce(this.getBackendItems(page), 500);
},
getBackendItems: function(page){
  this.$http.get("{{url('api/user/items')}}", {page : page}).success(function(response){
      this.items = response.data;
      this.last_page = response.last_page;
  });
},

Console.log 表示 getBackendItems 是一个函数,但仍然会抛出一个错误,指出没有将函数传递给 _.debounce() 调用。

2个回答

这有几个问题:

正确传递函数

当您尝试传递如下函数时: this.getBackendItems(page) 您正在运行它,因此 _.debounce 不会接收该函数,而是接收该函数的结果,在本例中为 Promise 对象。

  • this.getBackendItems 传递该函数
  • this.getBackendItems(page) 运行该函数并传递结果

但是,您如何告诉它要使用哪些参数?

正确调用去抖动函数

好吧, _.debounce() 返回您的原始函数,但包装了去抖动逻辑。因此,您将其缓存在变量中,并使用所需参数执行该函数 ( page )。因此,语法上正确的使用 debounce 的方式应该是这样的:

getItems: function(page){
  this.page = page;
  console.log(typeof(this.getBackendItems));
  var debouncedFunction = _.debounce(this.getBackendItems.bind(this), 500); // properly bind the function so "this" is the vue component.
  debouncedFunction(page)
},

对正确的函数进行去抖动

但是,这也行不通,因为 getItems 本身 没有 去抖动,因此这段代码将创建许多去抖动函数,这些函数将在 500ms 开始时全部触发。这不是一个好主意。

现在我的问题是:如何调用这个函数?从 v-on:click?然后 Vue 就帮你搞定了:

使用 Vue 的去抖动过滤器

<a v-on:click="getItems(page) | debounce 500">Some Link</a>

有了该过滤器,你根本不需要使用 _.debounce

如果你以其他方式调用此函数,请告诉我。

编辑:根据评论反馈进行更新:

在计算去抖动次数时使用去抖动函数

<a href="#"
  @click.prevent="getItems(page) | debounce 500" 
  @click="pageBuffer = pageBuffer +1">
  Click Me
</a>

JS:

var App = new Vue({
  el: '#app',
  data() {
    return {
            page: 1,
      pageBuffer: 0
    }
  },
  methods: {
    getItems: function(page) {
      this.getBackendItems(page + this.pageBuffer)
      this.pageBuffer = 0
    }
  }
})
Linus Borg
2016-04-10

以下是对我有用的解决方案:

<template>
  <div>
    <input type="text" v-model="term">
  </div>
</template>

<script>
export default {
  data() {
    return {
      term: ''
    }
  },

  watch: {
    term(value) {
      this.search(value)
    }
  },

  mounted() {
    this.search = _.debounce(this.getBackendItems.bind(this), 1000)
  },

  methods: {
    getBackendItems(value) {
      console.log(value)
      // ...
    }
  }
}
</script>
Alex Golovin
2019-08-01